Merge mozilla-central into electrolysis. One code change was required: in nsDocShell::CreateStaticClone I replaced EnsureDocShell with MaybeCreateDocShell.
authorBenjamin Smedberg <benjamin@smedbergs.us>
Sat, 12 Dec 2009 13:38:25 -0500
changeset 36174 7078aafa574a445e228b12175360f0ba3f47b9e6
parent 36173 0fe0641b2c400cd609a959f2205824cf9fc6edeb (current diff)
parent 35634 8d196765d647b8400b095afcecfb398bbfe7df6c (diff)
child 36175 4778341de66c04612e42500507411902431227b3
push idunknown
push userunknown
push dateunknown
milestone1.9.3a1pre
Merge mozilla-central into electrolysis. One code change was required: in nsDocShell::CreateStaticClone I replaced EnsureDocShell with MaybeCreateDocShell.
accessible/tests/mochitest/test_invalidate_elmli.html
accessible/tests/mochitest/test_nsIAccessible_applicationAccessible.html
accessible/tests/mochitest/test_selectable_tree.xul
build/automation.py.in
configure.in
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsGkAtomList.h
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.h
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/smil/nsISMILCSSValueType.h
docshell/base/nsDocShell.cpp
layout/generic/nsObjectFrame.cpp
nsprpub/configure
testing/testsuite-targets.mk
widget/src/windows/nsDeviceContextSpecWin.cpp
widget/src/windows/nsWindow.cpp
--- a/accessible/public/nsIAccessibilityService.idl
+++ b/accessible/public/nsIAccessibilityService.idl
@@ -41,17 +41,17 @@
 
 interface nsIAccessibleEventListener;
 interface nsIDocument;
 interface nsIFrame;
 interface nsObjectFrame;
 interface nsIContent;
 interface nsITimer;
 
-[uuid(29384ba1-f9ce-425d-afb5-54e2ee949d87)]
+[uuid(61098f48-4fcc-4b05-9cf3-c11b8efbe682)]
 interface nsIAccessibilityService : nsIAccessibleRetrieval
 {
   nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
   nsIAccessible createRootAccessible(in nsIPresShell aShell, in nsIDocument aDocument);
 
   nsIAccessible createHTML4ButtonAccessible(in nsIFrame aFrame);
   nsIAccessible createHyperTextAccessible(in nsIFrame aFrame);
   nsIAccessible createHTMLBRAccessible(in nsIFrame aFrame);
@@ -71,19 +71,28 @@ interface nsIAccessibilityService : nsIA
   nsIAccessible createHTMLRadioButtonAccessible(in nsIFrame aFrame);
   nsIAccessible createHTMLSelectOptionAccessible(in nsIDOMNode aNode, in nsIAccessible aAccParent, in nsIWeakReference aPresShell);
   nsIAccessible createHTMLTableAccessible(in nsIFrame aFrame);
   nsIAccessible createHTMLTableCellAccessible(in nsIFrame aFrame);
   nsIAccessible createHTMLTextAccessible(in nsIFrame aFrame);
   nsIAccessible createHTMLTextFieldAccessible(in nsIFrame aFrame);
   nsIAccessible createHTMLCaptionAccessible(in nsIFrame aFrame);
 
-  nsIAccessible getAccessible(in nsIDOMNode aNode, in nsIPresShell aPresShell,                          
-                              in nsIWeakReference aWeakShell, 
-                              inout nsIFrame frameHint, out boolean aIsHidden);
+  /**
+   * Return an accessible for the given DOM node.
+   *
+   * @param  aNode       [in] the given node
+   * @param  aPresShell  [in] the pres shell of the node
+   * @param  aWeakShell  [in] the weak shell for the pres shell
+   * @param  aFrameHint  [in] the frame of the given node
+   * @param  aIsHidden   [out] indicates whether the node's frame is hidden
+   */
+  nsIAccessible getAccessible(in nsIDOMNode aNode, in nsIPresShell aPresShell,
+                              in nsIWeakReference aWeakShell,
+                              in nsIFrame aFrameHint, out boolean aIsHidden);
 
   // For gtk+ native window accessible
   nsIAccessible addNativeRootAccessible(in voidPtr aAtkAccessible);
   void removeNativeRootAccessible(in nsIAccessible aRootAccessible);
 
   /**
    * Used to describe sort of changes leading to accessible tree invalidation.
    */
--- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp
@@ -642,18 +642,17 @@ nsApplicationAccessibleWrap::AddRootAcce
 
     // add by weak reference
     nsresult rv = nsApplicationAccessible::AddRootAccessible(aRootAccWrap);
     NS_ENSURE_SUCCESS(rv, rv);
 
     AtkObject *atkAccessible = nsAccessibleWrap::GetAtkObject(aRootAccWrap);
     atk_object_set_parent(atkAccessible, mAtkObject);
 
-    PRUint32 count = 0;
-    mChildren->GetLength(&count);
+    PRUint32 count = mChildren.Count();
     g_signal_emit_by_name(mAtkObject, "children_changed::add", count - 1,
                           atkAccessible, NULL);
 
 #ifdef MAI_LOGGING
     if (NS_SUCCEEDED(rv)) {
         MAI_LOG_DEBUG(("\nAdd RootAcc=%p OK, count=%d\n",
                        (void*)aRootAccWrap, count));
     }
@@ -665,46 +664,37 @@ nsApplicationAccessibleWrap::AddRootAcce
     return rv;
 }
 
 nsresult
 nsApplicationAccessibleWrap::RemoveRootAccessible(nsIAccessible *aRootAccWrap)
 {
     NS_ENSURE_ARG_POINTER(aRootAccWrap);
 
-    PRUint32 index = 0;
-    nsresult rv = NS_ERROR_FAILURE;
-
-    // we must use weak ref to get the index
-    nsCOMPtr<nsIWeakReference> weakPtr = do_GetWeakReference(aRootAccWrap);
-    rv = mChildren->IndexOf(0, weakPtr, &index);
+    PRInt32 index = mChildren.IndexOf(aRootAccWrap);
 
     AtkObject *atkAccessible = nsAccessibleWrap::GetAtkObject(aRootAccWrap);
     atk_object_set_parent(atkAccessible, NULL);
     g_signal_emit_by_name(mAtkObject, "children_changed::remove", index,
                           atkAccessible, NULL);
 
+    nsresult rv = nsApplicationAccessible::RemoveRootAccessible(aRootAccWrap);
+
 #ifdef MAI_LOGGING
-    PRUint32 count = 0;
-    mChildren->GetLength(&count);
+    PRUint32 count = mChildren.Count();
 
     if (NS_SUCCEEDED(rv)) {
-        rv = mChildren->RemoveElementAt(index);
         MAI_LOG_DEBUG(("\nRemove RootAcc=%p, count=%d\n",
                        (void*)aRootAccWrap, (count-1)));
     }
     else
         MAI_LOG_DEBUG(("\nFail to Remove RootAcc=%p, count=%d\n",
                        (void*)aRootAccWrap, count));
-#else
-    NS_ENSURE_SUCCESS(rv, rv);
-    rv = mChildren->RemoveElementAt(index);
+#endif
 
-#endif
-    InvalidateChildren();
     return rv;
 }
 
 void
 nsApplicationAccessibleWrap::PreCreate()
 {
     if (!sATKChecked) {
         sATKLib = PR_LoadLibrary(sATKLibName);
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -497,16 +497,56 @@ nsAccUtils::GetARIATreeItemParent(nsIAcc
     role = nsAccUtils::Role(prevAccessible);
   }
   if (role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
     // Previous sibling of parent group is a tree item -- this is the conceptual tree item parent
     NS_ADDREF(*aTreeItemParentResult = prevAccessible);
   }
 }
 
+already_AddRefed<nsIAccessible>
+nsAccUtils::GetSelectableContainer(nsIAccessible *aAccessible, PRUint32 aState)
+{
+  if (!aAccessible)
+    return nsnull;
+
+  if (!(aState & nsIAccessibleStates::STATE_SELECTABLE))
+    return nsnull;
+
+  nsCOMPtr<nsIAccessibleSelectable> container;
+  nsCOMPtr<nsIAccessible> parent, accessible(aAccessible);
+  while (!container) {
+    accessible->GetParent(getter_AddRefs(parent));
+
+    if (!parent || Role(parent) == nsIAccessibleRole::ROLE_PANE)
+      return nsnull;
+
+    container = do_QueryInterface(parent);
+    parent.swap(accessible);
+  }
+
+  return accessible.forget();
+}
+
+already_AddRefed<nsIAccessible>
+nsAccUtils::GetMultiSelectableContainer(nsIDOMNode *aNode)
+{
+  nsCOMPtr<nsIAccessible> accessible;
+  nsAccessNode::GetAccService()->GetAccessibleFor(aNode,
+                                                  getter_AddRefs(accessible));
+
+  nsCOMPtr<nsIAccessible> container =
+    GetSelectableContainer(accessible, State(accessible));
+
+  if (State(container) & nsIAccessibleStates::STATE_MULTISELECTABLE)
+    return container.forget();
+
+  return nsnull;
+}
+
 PRBool
 nsAccUtils::IsARIASelected(nsIAccessible *aAccessible)
 {
   nsRefPtr<nsAccessible> acc = nsAccUtils::QueryAccessible(aAccessible);
   nsCOMPtr<nsIDOMNode> node;
   acc->GetDOMNode(getter_AddRefs(node));
   NS_ASSERTION(node, "No DOM node!");
 
@@ -922,47 +962,16 @@ PRBool
 nsAccUtils::IsNodeRelevant(nsIDOMNode *aNode)
 {
   nsCOMPtr<nsIDOMNode> relevantNode;
   nsAccessNode::GetAccService()->GetRelevantContentNodeFor(aNode,
                                                            getter_AddRefs(relevantNode));
   return aNode == relevantNode;
 }
 
-already_AddRefed<nsIAccessible>
-nsAccUtils::GetMultiSelectFor(nsIDOMNode *aNode)
-{
-  if (!aNode)
-    return nsnull;
-
-  nsCOMPtr<nsIAccessible> accessible;
-  nsAccessNode::GetAccService()->GetAccessibleFor(aNode,
-                                                  getter_AddRefs(accessible));
-  if (!accessible)
-    return nsnull;
-
-  PRUint32 state = State(accessible);
-  if (0 == (state & nsIAccessibleStates::STATE_SELECTABLE))
-    return nsnull;
-
-  while (0 == (state & nsIAccessibleStates::STATE_MULTISELECTABLE)) {
-    nsIAccessible *current = accessible;
-    current->GetParent(getter_AddRefs(accessible));
-    if (!accessible ||
-        nsAccUtils::Role(accessible) == nsIAccessibleRole::ROLE_PANE) {
-      return nsnull;
-    }
-    state = State(accessible);
-  }
-
-  nsIAccessible *returnAccessible = nsnull;
-  accessible.swap(returnAccessible);
-  return returnAccessible;
-}
-
 nsresult
 nsAccUtils::GetHeaderCellsFor(nsIAccessibleTable *aTable,
                               nsIAccessibleTableCell *aCell,
                               PRInt32 aRowOrColHeaderCells, nsIArray **aCells)
 {
   nsresult rv = NS_OK;
   nsCOMPtr<nsIMutableArray> cells = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -175,16 +175,31 @@ public:
      * @param The tree item's parent, or null if none
      */
    static void
      GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
                            nsIContent *aStartTreeItemContent,
                            nsIAccessible **aTreeItemParent);
 
   /**
+   * Return single or multi selectable container for the given item.
+   *
+   * @param  aAccessible  [in] the item accessible
+   * @param  aState       [in] the state of the item accessible
+   */
+  static already_AddRefed<nsIAccessible>
+    GetSelectableContainer(nsIAccessible *aAccessible, PRUint32 aState);
+
+  /**
+   * Return multi selectable container for the given item.
+   */
+  static already_AddRefed<nsIAccessible>
+    GetMultiSelectableContainer(nsIDOMNode *aNode);
+
+  /**
    * Return true if the DOM node of given accessible has aria-selected="true"
    * attribute.
    */
   static PRBool IsARIASelected(nsIAccessible *aAccessible);
 
   /**
    * Return text accessible containing focus point of the given selection.
    * Used for normal and misspelling selection changes processing.
@@ -463,21 +478,16 @@ public:
 
   /**
    * Return true if the given node can be accessible and attached to
    * the document's accessible tree.
    */
   static PRBool IsNodeRelevant(nsIDOMNode *aNode);
 
   /**
-   * Return multiselectable parent for the given selectable accessible if any.
-   */
-  static already_AddRefed<nsIAccessible> GetMultiSelectFor(nsIDOMNode *aNode);
-
-  /**
    * Search hint enum constants. Used by GetHeaderCellsFor() method.
    */
   enum {
     // search for row header cells, left direction
     eRowHeaderCells,
     // search for column header cells, top direction
     eColumnHeaderCells
   };
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -1237,37 +1237,35 @@ NS_IMETHODIMP nsAccessibilityService::Ge
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
   NS_ENSURE_ARG(aNode);
   NS_ENSURE_ARG(aPresShell);
 
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
-  nsIFrame *outFrameUnused = NULL;
   PRBool isHiddenUnused = false;
   return GetAccessible(aNode, aPresShell, weakShell, 
-                       &outFrameUnused, &isHiddenUnused, aAccessible);
+                       nsnull, &isHiddenUnused, aAccessible);
 }
 
 NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWeakShell(nsIDOMNode *aNode, 
                                                                nsIWeakReference *aWeakShell,
                                                                nsIAccessible **aAccessible) 
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
   NS_ENSURE_ARG(aNode);
   NS_ENSURE_ARG(aWeakShell);
 
   nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(aWeakShell));
-  nsIFrame *outFrameUnused = NULL;
   PRBool isHiddenUnused = false;
   return GetAccessible(aNode, presShell, aWeakShell, 
-                       &outFrameUnused, &isHiddenUnused, aAccessible);
+                       nsnull, &isHiddenUnused, aAccessible);
 }
 
 nsresult nsAccessibilityService::InitAccessible(nsIAccessible *aAccessibleIn,
                                                 nsIAccessible **aAccessibleOut,
                                                 nsRoleMapEntry *aRoleMapEntry)
 {
   if (!aAccessibleIn) {
     return NS_ERROR_FAILURE; // No accessible to init
@@ -1310,36 +1308,36 @@ static PRBool HasRelatedContent(nsIConte
   }
 
   return PR_FALSE;
 }
 
 NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode,
                                                     nsIPresShell *aPresShell,
                                                     nsIWeakReference *aWeakShell,
-                                                    nsIFrame **aFrameHint,
+                                                    nsIFrame *aFrameHint,
                                                     PRBool *aIsHidden,
                                                     nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
-  NS_ENSURE_ARG_POINTER(aFrameHint);
   *aAccessible = nsnull;
+
   if (!aPresShell || !aWeakShell || gIsShutdown) {
     return NS_ERROR_FAILURE;
   }
 
   NS_ASSERTION(aNode, "GetAccessible() called with no node.");
 
   *aIsHidden = PR_FALSE;
 
   // Frames can be deallocated when we flush layout, or when we call into code
   // that can flush layout, either directly, or via DOM manipulation, or some
   // CSS styles like :hover. We use the weak frame checks to avoid calling
   // methods on a dead frame pointer.
-  nsWeakFrame weakFrame(*aFrameHint);
+  nsWeakFrame weakFrame(aFrameHint);
 
 #ifdef DEBUG_A11Y
   // Please leave this in for now, it's a convenient debugging method
   nsAutoString name;
   aNode->GetLocalName(name);
   if (name.LowerCaseEqualsLiteral("h1")) 
     printf("## aaronl debugging tag name\n");
 
@@ -1386,17 +1384,16 @@ NS_IMETHODIMP nsAccessibilityService::Ge
     if (accessibleDoc) {
       newAcc = do_QueryInterface(accessibleDoc);
       NS_ASSERTION(newAcc, "nsIAccessibleDocument is not an nsIAccessible");
     }
     else {
       CreateRootAccessible(aPresShell, nodeIsDoc, getter_AddRefs(newAcc)); // Does Init() for us
     }
 
-    *aFrameHint = aPresShell->GetRootFrame();
     NS_IF_ADDREF(*aAccessible = newAcc);
     return NS_OK;
   }
 
   NS_ASSERTION(content->GetDocument(), "Creating accessible for node with no document");
   if (!content->GetDocument()) {
     return NS_ERROR_FAILURE;
   }
@@ -1416,17 +1413,17 @@ NS_IMETHODIMP nsAccessibilityService::Ge
     weakFrame = aPresShell->GetRealPrimaryFrameFor(content);
     if (weakFrame.GetFrame()) {
 #ifdef DEBUG_A11Y_FRAME_OPTIMIZATION
       // Frame hint debugging
       ++frameHintFailed;
       if (content->IsNodeOfType(nsINode::eTEXT)) {
         ++frameHintFailedForText;
       }
-      frameHintNonexistant += !*aFrameHint;
+      frameHintNonexistant += !aFrameHint;
       printf("Frame hint failures: %d / %d . Text fails = %d. No hint fails = %d \n", frameHintFailed, frameHintTried, frameHintFailedForText, frameHintNonexistant);
       if (frameHintTried >= 354) {
         printf("* "); // Aaron's break point
       }
 #endif
       if (weakFrame.GetFrame()->GetContent() != content) {
         // Not the main content for this frame!
         // For example, this happens because <area> elements return the
@@ -1445,89 +1442,78 @@ NS_IMETHODIMP nsAccessibilityService::Ge
             imageAcc->GetChildCount(&childCount);
             // area accessible should be in cache now
             return GetCachedAccessible(aNode, aWeakShell, aAccessible);
           }
         }
 
         return NS_OK;
       }
-      *aFrameHint = weakFrame.GetFrame();
     }
   }
 
   // Check frame to see if it is hidden
   if (!weakFrame.GetFrame() ||
       !weakFrame.GetFrame()->GetStyleVisibility()->IsVisible()) {
     *aIsHidden = PR_TRUE;
   }
 
-  if (*aIsHidden) {
-    *aFrameHint = weakFrame.GetFrame();
+  if (*aIsHidden)
     return NS_OK;
-  }
 
   /**
    * Attempt to create an accessible based on what we know
    */
   if (content->IsNodeOfType(nsINode::eTEXT)) {
     // --- Create HTML for visible text frames ---
     nsIFrame* f = weakFrame.GetFrame();
     if (f && f->IsEmpty()) {
       nsAutoString renderedWhitespace;
       f->GetRenderedText(&renderedWhitespace, nsnull, nsnull, 0, 1);
       if (renderedWhitespace.IsEmpty()) {
         // Really empty -- nothing is rendered
         *aIsHidden = PR_TRUE;
-        *aFrameHint = weakFrame.GetFrame();
         return NS_OK;
       }
     }
     if (weakFrame.IsAlive()) {
       weakFrame.GetFrame()->GetAccessible(getter_AddRefs(newAcc));
     }
 
-    nsresult rv = InitAccessible(newAcc, aAccessible, nsnull);
-    *aFrameHint = weakFrame.GetFrame();
-    return rv;
+    return InitAccessible(newAcc, aAccessible, nsnull);
   }
 
   PRBool isHTML = content->IsHTML();
   if (isHTML && content->Tag() == nsAccessibilityAtoms::map) {
     // Create hyper text accessible for HTML map if it is used to group links
     // (see http://www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass). If the HTML
     // map doesn't have 'name' attribute (or has empty name attribute) then we
     // suppose it is used for links grouping. Otherwise we think it is used in
     // conjuction with HTML image element and in this case we don't create any
     // accessible for it and don't walk into it. The accessibles for HTML area
     // (nsHTMLAreaAccessible) the map contains are attached as children of the
     // appropriate accessible for HTML image (nsHTMLImageAccessible).
     nsAutoString name;
     content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::name, name);
     if (!name.IsEmpty()) {
       *aIsHidden = PR_TRUE;
-      *aFrameHint = weakFrame.GetFrame();
       return NS_OK;
     }
     
     nsresult rv =
       CreateHyperTextAccessible(weakFrame.GetFrame(), getter_AddRefs(newAcc));
-    if (NS_FAILED(rv)) {
-      *aFrameHint = weakFrame.GetFrame();
-      return rv;
-    }
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
   if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation") &&
       !content->IsFocusable()) { // For presentation only
     // Only create accessible for role of "presentation" if it is focusable --
     // in that case we need an accessible in case it gets focused, we
     // don't want focus ever to be 'lost'
-    *aFrameHint = weakFrame.GetFrame();
     return NS_OK;
   }
 
   if (weakFrame.IsAlive() && !newAcc && isHTML) {  // HTML accessibles
     PRBool tryTagNameOrFrame = PR_TRUE;
 
     nsIAtom *frameType = weakFrame.GetFrame()->GetType();
 
@@ -1575,17 +1561,16 @@ NS_IMETHODIMP nsAccessibilityService::Ge
                        "No accessible for parent table and it didn't have role of presentation");
 #endif
 
           if (!roleMapEntry && !content->IsFocusable()) {
             // Table-related descendants of presentation table are also
             // presentation if they aren't focusable and have not explicit ARIA
             // role (don't create accessibles for them unless they need to fire
             // focus events).
-            *aFrameHint = weakFrame.GetFrame();
             return NS_OK;
           }
 
           // otherwise create ARIA based accessible.
           tryTagNameOrFrame = PR_FALSE;
           break;
         }
 
@@ -1623,20 +1608,17 @@ NS_IMETHODIMP nsAccessibilityService::Ge
       // Prefer to use markup (mostly tag name, perhaps attributes) to
       // decide if and what kind of accessible to create.
       // The method creates accessibles for table related content too therefore
       // we do not call it if accessibles for table related content are
       // prevented above.
       nsresult rv =
         CreateHTMLAccessibleByMarkup(weakFrame.GetFrame(), aWeakShell, aNode,
                                      getter_AddRefs(newAcc));
-      if (NS_FAILED(rv)) {
-        *aFrameHint = weakFrame.GetFrame();
-        return rv;
-      }
+      NS_ENSURE_SUCCESS(rv, rv);
 
       if (!newAcc) {
         // Do not create accessible object subtrees for non-rendered table
         // captions. This could not be done in
         // nsTableCaptionFrame::GetAccessible() because the descendants of
         // the table caption would still be created. By setting
         // *aIsHidden = PR_TRUE we ensure that no descendant accessibles are
         // created.
@@ -1644,32 +1626,28 @@ NS_IMETHODIMP nsAccessibilityService::Ge
         if (!f) {
           f = aPresShell->GetRealPrimaryFrameFor(content);
         }
         if (f->GetType() == nsAccessibilityAtoms::tableCaptionFrame &&
            f->GetRect().IsEmpty()) {
           // XXX This is not the ideal place for this code, but right now there
           // is no better place:
           *aIsHidden = PR_TRUE;
-          *aFrameHint = weakFrame.GetFrame();
           return NS_OK;
         }
         f->GetAccessible(getter_AddRefs(newAcc)); // Try using frame to do it
       }
     }
   }
 
   if (!newAcc) {
     // Elements may implement nsIAccessibleProvider via XBL. This allows them to
     // say what kind of accessible to create.
     nsresult rv = GetAccessibleByType(aNode, getter_AddRefs(newAcc));
-    if (NS_FAILED(rv)) {
-      *aFrameHint = weakFrame.GetFrame();
-      return rv;
-    }
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (!newAcc) {
     // Create generic accessibles for SVG and MathML nodes.
     if (content->GetNameSpaceID() == kNameSpaceID_SVG &&
         content->Tag() == nsAccessibilityAtoms::svg) {
       newAcc = new nsEnumRoleAccessible(aNode, aWeakShell,
                                         nsIAccessibleRole::ROLE_DIAGRAM);
@@ -1702,19 +1680,17 @@ NS_IMETHODIMP nsAccessibilityService::Ge
       CreateHyperTextAccessible(weakFrame.GetFrame(), getter_AddRefs(newAcc));
     }
     else {  // XUL, SVG, MathML etc.
       // Interesting generic non-HTML container
       newAcc = new nsAccessibleWrap(aNode, aWeakShell);
     }
   }
 
-  nsresult rv = InitAccessible(newAcc, aAccessible, roleMapEntry);
-  *aFrameHint = weakFrame.GetFrame();
-  return rv;
+  return InitAccessible(newAcc, aAccessible, roleMapEntry);
 }
 
 PRBool
 nsAccessibilityService::HasUniversalAriaProperty(nsIContent *aContent,
                                                  nsIWeakReference *aWeakShell)
 {
   // ARIA attributes that take token values (NMTOKEN, bool) are special cased.
   return nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_atomic) ||
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -144,24 +144,22 @@ nsAccessibleDOMStringList::Contains(cons
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible. nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsAccessible, nsAccessNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstChild)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNextSibling)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mChildren)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsAccessible, nsAccessNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstChild)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNextSibling)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mChildren)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ADDREF_INHERITED(nsAccessible, nsAccessNode)
 NS_IMPL_RELEASE_INHERITED(nsAccessible, nsAccessNode)
 
 nsresult nsAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
   // Custom-built QueryInterface() knows when we support nsIAccessibleSelectable
@@ -181,33 +179,29 @@ nsresult nsAccessible::QueryInterface(RE
 
   if (aIID.Equals(NS_GET_IID(nsAccessible))) {
     *aInstancePtr = static_cast<nsAccessible*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
   }
 
   if (aIID.Equals(NS_GET_IID(nsIAccessibleSelectable))) {
-    nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
-    if (!content) {
-      return NS_ERROR_FAILURE; // This accessible has been shut down
-    }
-    if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) {
-      // If we have an XHTML role attribute present and the
-      // aria-multiselectable attribute is true, then we need
-      // to support nsIAccessibleSelectable
+    if (mRoleMapEntry &&
+        (mRoleMapEntry->attributeMap1 == eARIAMultiSelectable ||
+         mRoleMapEntry->attributeMap2 == eARIAMultiSelectable ||
+         mRoleMapEntry->attributeMap3 == eARIAMultiSelectable)) {
+
+      // If we have an ARIA role attribute present and the role allows multi
+      // selectable state, then we need to support nsIAccessibleSelectable.
       // If either attribute (role or multiselectable) change, then we'll
       // destroy this accessible so that we can follow COM identity rules.
-      nsAutoString multiselectable;
-      if (content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::aria_multiselectable,
-                               nsAccessibilityAtoms::_true, eCaseMatters)) {
-        *aInstancePtr = static_cast<nsIAccessibleSelectable*>(this);
-        NS_ADDREF_THIS();
-        return NS_OK;
-      }
+
+      *aInstancePtr = static_cast<nsIAccessibleSelectable*>(this);
+      NS_ADDREF_THIS();
+      return NS_OK;
     }
   }
 
   if (aIID.Equals(NS_GET_IID(nsIAccessibleValue))) {
     if (mRoleMapEntry && mRoleMapEntry->valueRule != eNoValue) {
       *aInstancePtr = static_cast<nsIAccessibleValue*>(this);
       NS_ADDREF_THIS();
       return NS_OK;
@@ -224,18 +218,18 @@ nsresult nsAccessible::QueryInterface(RE
     }
     return NS_ERROR_NO_INTERFACE;
   }
 
   return nsAccessNodeWrap::QueryInterface(aIID, aInstancePtr);
 }
 
 nsAccessible::nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell): nsAccessNodeWrap(aNode, aShell), 
-  mParent(nsnull), mFirstChild(nsnull), mNextSibling(nsnull), mRoleMapEntry(nsnull),
-  mAccChildCount(eChildCountUninitialized)
+  mParent(nsnull), mRoleMapEntry(nsnull),
+  mAreChildrenInitialized(PR_FALSE)
 {
 #ifdef NS_DEBUG_X
    {
      nsCOMPtr<nsIPresShell> shell(do_QueryReferent(aShell));
      printf(">>> %p Created Acc - DOM: %p  PS: %p", 
             (void*)static_cast<nsIAccessible*>(this), (void*)aNode,
             (void*)shell.get());
     nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
@@ -477,376 +471,177 @@ nsAccessible::GetKeyboardShortcut(nsAStr
     propertyKey.AssignLiteral("VK_CONTROL");
     nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
   }
 
   aAccessKey = accesskey;
   return NS_OK;
 }
 
-void
-nsAccessible::SetParent(nsIAccessible *aParent)
-{
-  if (mParent != aParent) {
-    // Adopt a child -- we allow this now. the new parent
-    // may be a dom node which wasn't previously accessible but now is.
-    // The old parent's children now need to be invalidated, since 
-    // it no longer owns the child, the new parent does
-    nsRefPtr<nsAccessible> oldParent = nsAccUtils::QueryAccessible(mParent);
-    if (oldParent)
-      oldParent->InvalidateChildren();
-  }
-
-  mParent = aParent;
-}
-
-void
-nsAccessible::SetFirstChild(nsIAccessible *aFirstChild)
-{
-  mFirstChild = aFirstChild;
-}
-
-void
-nsAccessible::SetNextSibling(nsIAccessible *aNextSibling)
-{
-  mNextSibling = aNextSibling;
-}
-
 nsresult
 nsAccessible::Shutdown()
 {
-  mNextSibling = nsnull;
-
   // Invalidate the child count and pointers to other accessibles, also make
   // sure none of its children point to this parent
   InvalidateChildren();
   if (mParent) {
     nsRefPtr<nsAccessible> parent(nsAccUtils::QueryAccessible(mParent));
     parent->InvalidateChildren();
     mParent = nsnull;
   }
 
   return nsAccessNodeWrap::Shutdown();
 }
 
-void
-nsAccessible::InvalidateChildren()
-{
-  // Document has transformed, reset our invalid children and child count
-
-  // Reset the sibling pointers, they will be set up again the next time
-  // CacheChildren() is called.
-  // Note: we don't want to start creating accessibles at this point,
-  // so don't use GetNextSibling() here. (bug 387252)
-  nsRefPtr<nsAccessible> child = nsAccUtils::QueryAccessible(mFirstChild);
-  while (child) {
-    child->mParent = nsnull;
-
-    nsCOMPtr<nsIAccessible> next = child->mNextSibling;
-    child->mNextSibling = nsnull;
-    child = nsAccUtils::QueryAccessible(next);
-  }
-
-  mAccChildCount = eChildCountUninitialized;
-  mFirstChild = nsnull;
-}
-
 NS_IMETHODIMP
 nsAccessible::GetParent(nsIAccessible **aParent)
 {
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsIAccessible> cachedParent = GetCachedParent();
-  if (cachedParent) {
-    cachedParent.swap(*aParent);
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
-  NS_ENSURE_TRUE(docAccessible, NS_ERROR_FAILURE);
-
-  return docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, aParent);
-}
-
-already_AddRefed<nsIAccessible>
-nsAccessible::GetCachedParent()
-{
-  if (IsDefunct())
-    return nsnull;
-
-  nsCOMPtr<nsIAccessible> cachedParent = mParent;
-  return cachedParent.forget();
-}
-
-already_AddRefed<nsIAccessible>
-nsAccessible::GetCachedFirstChild()
-{
-  if (IsDefunct())
-    return nsnull;
-
-  nsCOMPtr<nsIAccessible> cachedFirstChild = mFirstChild;
-  return cachedFirstChild.forget();
+  NS_ENSURE_ARG_POINTER(aParent);
+
+  NS_IF_ADDREF(*aParent = GetParent());
+  return *aParent ? NS_OK : NS_ERROR_FAILURE;
 }
 
   /* readonly attribute nsIAccessible nextSibling; */
-NS_IMETHODIMP nsAccessible::GetNextSibling(nsIAccessible * *aNextSibling) 
-{ 
-  *aNextSibling = nsnull; 
-  if (!mWeakShell) {
-    // This node has been shut down
-    return NS_ERROR_FAILURE;
-  }
-  if (!mParent) {
-    nsCOMPtr<nsIAccessible> parent(GetParent());
-    if (parent) {
-      PRInt32 numChildren;
-      parent->GetChildCount(&numChildren);  // Make sure we cache all of the children
-    }
-  }
-
-  if (mNextSibling || !mParent) {
-    // If no parent, don't try to calculate a new sibling
-    // It either means we're at the root or shutting down the parent
-    NS_IF_ADDREF(*aNextSibling = mNextSibling);
-
-    return NS_OK;
-  }
-
-  return NS_ERROR_FAILURE;
+NS_IMETHODIMP
+nsAccessible::GetNextSibling(nsIAccessible **aNextSibling) 
+{
+  NS_ENSURE_ARG_POINTER(aNextSibling);
+
+  nsresult rv = NS_OK;
+  NS_IF_ADDREF(*aNextSibling = GetSiblingAtOffset(1, &rv));
+  return rv;
 }
 
   /* readonly attribute nsIAccessible previousSibling; */
-NS_IMETHODIMP nsAccessible::GetPreviousSibling(nsIAccessible * *aPreviousSibling) 
+NS_IMETHODIMP
+nsAccessible::GetPreviousSibling(nsIAccessible * *aPreviousSibling) 
 {
-  *aPreviousSibling = nsnull;
-
-  if (!mWeakShell) {
-    // This node has been shut down
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIAccessible> parent;
-  if (NS_FAILED(GetParent(getter_AddRefs(parent))) || !parent) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIAccessible> testAccessible, prevSibling;
-  parent->GetFirstChild(getter_AddRefs(testAccessible));
-  while (testAccessible && this != testAccessible) {
-    prevSibling = testAccessible;
-    prevSibling->GetNextSibling(getter_AddRefs(testAccessible));
-  }
-
-  if (!prevSibling) {
-    return NS_ERROR_FAILURE;
-  }
-
-  NS_ADDREF(*aPreviousSibling = prevSibling);
-  return NS_OK;
+  NS_ENSURE_ARG_POINTER(aPreviousSibling);
+
+  nsresult rv = NS_OK;
+  NS_IF_ADDREF(*aPreviousSibling = GetSiblingAtOffset(-1, &rv));
+  return rv;
 }
 
   /* readonly attribute nsIAccessible firstChild; */
-NS_IMETHODIMP nsAccessible::GetFirstChild(nsIAccessible * *aFirstChild) 
-{  
-  if (gIsCacheDisabled) {
+NS_IMETHODIMP
+nsAccessible::GetFirstChild(nsIAccessible **aFirstChild) 
+{
+  NS_ENSURE_ARG_POINTER(aFirstChild);
+  *aFirstChild = nsnull;
+
+  if (gIsCacheDisabled)
     InvalidateChildren();
-  }
-  PRInt32 numChildren;
-  GetChildCount(&numChildren);  // Make sure we cache all of the children
-
-#ifdef DEBUG
-  nsRefPtr<nsAccessible> firstChild(nsAccUtils::QueryAccessible(mFirstChild));
-  if (firstChild) {
-    nsCOMPtr<nsIAccessible> realParent = firstChild->GetCachedParent();
-    NS_ASSERTION(!realParent || realParent == this,
-                 "Two accessibles have the same first child accessible.");
-  }
-#endif
-
-  NS_IF_ADDREF(*aFirstChild = mFirstChild);
-
-  return NS_OK;  
+
+  PRInt32 childCount = GetChildCount();
+  NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
+
+  if (childCount > 0)
+    NS_ADDREF(*aFirstChild = GetChildAt(0));
+
+  return NS_OK;
 }
 
   /* readonly attribute nsIAccessible lastChild; */
-NS_IMETHODIMP nsAccessible::GetLastChild(nsIAccessible * *aLastChild)
-{  
-  GetChildAt(-1, aLastChild);
+NS_IMETHODIMP
+nsAccessible::GetLastChild(nsIAccessible **aLastChild)
+{
+  NS_ENSURE_ARG_POINTER(aLastChild);
+  *aLastChild = nsnull;
+
+  PRInt32 childCount = GetChildCount();
+  NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
+
+  NS_IF_ADDREF(*aLastChild = GetChildAt(childCount - 1));
   return NS_OK;
 }
 
-NS_IMETHODIMP nsAccessible::GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild)
+NS_IMETHODIMP
+nsAccessible::GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild)
 {
-  // aChildNum is a zero-based index
-
-  PRInt32 numChildren;
-  GetChildCount(&numChildren);
-
-  // If no children or aChildNum is larger than numChildren, return null
-  if (aChildNum >= numChildren || numChildren == 0 || !mWeakShell) {
-    *aChild = nsnull;
-    return NS_ERROR_FAILURE;
-  // If aChildNum is less than zero, set aChild to last index
-  } else if (aChildNum < 0) {
-    aChildNum = numChildren - 1;
-  }
-
-  nsCOMPtr<nsIAccessible> current(mFirstChild), nextSibling;
-  PRInt32 index = 0;
-
-  while (current) {
-    nextSibling = current;
-    if (++index > aChildNum) {
-      break;
-    }
-    nextSibling->GetNextSibling(getter_AddRefs(current));
-  }
-
-  NS_IF_ADDREF(*aChild = nextSibling);
-
+  NS_ENSURE_ARG_POINTER(aChild);
+  *aChild = nsnull;
+
+  PRInt32 childCount = GetChildCount();
+  NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
+
+  // If child index is negative, then return last child.
+  // XXX: do we really need this?
+  if (aChildIndex < 0)
+    aChildIndex = childCount - 1;
+
+  nsIAccessible* child = GetChildAt(aChildIndex);
+  if (!child)
+    return NS_ERROR_INVALID_ARG;
+
+  NS_ADDREF(*aChild = child);
   return NS_OK;
 }
 
 // readonly attribute nsIArray children;
-NS_IMETHODIMP nsAccessible::GetChildren(nsIArray **aOutChildren)
+NS_IMETHODIMP
+nsAccessible::GetChildren(nsIArray **aOutChildren)
 {
+  NS_ENSURE_ARG_POINTER(aOutChildren);
   *aOutChildren = nsnull;
-  nsCOMPtr<nsIMutableArray> children = do_CreateInstance(NS_ARRAY_CONTRACTID);
-  if (!children)
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsIAccessible> curChild;
-  while (NextChild(curChild)) {
-    children->AppendElement(curChild, PR_FALSE);
+
+  PRInt32 childCount = GetChildCount();
+  NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
+
+  nsresult rv = NS_OK;
+  nsCOMPtr<nsIMutableArray> children =
+    do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsIAccessible* child = GetChildAt(childIdx);
+    children->AppendElement(child, PR_FALSE);
   }
-  
+
   NS_ADDREF(*aOutChildren = children);
   return NS_OK;
 }
 
 nsIAccessible *nsAccessible::NextChild(nsCOMPtr<nsIAccessible>& aAccessible)
 {
   nsCOMPtr<nsIAccessible> nextChild;
   if (!aAccessible) {
     GetFirstChild(getter_AddRefs(nextChild));
   }
   else {
     aAccessible->GetNextSibling(getter_AddRefs(nextChild));
   }
   return (aAccessible = nextChild);
 }
 
-void nsAccessible::CacheChildren()
-{
-  if (!mWeakShell) {
-    // This node has been shut down
-    mAccChildCount = eChildCountUninitialized;
-    return;
-  }
-
-  if (mAccChildCount == eChildCountUninitialized) {
-    mAccChildCount = 0;// Prevent reentry
-    PRBool allowsAnonChildren = GetAllowsAnonChildAccessibles();
-    nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
-    // Seed the frame hint early while we're still on a container node.
-    // This is better than doing the GetPrimaryFrameFor() later on
-    // a text node, because text nodes aren't in the frame map.
-    walker.mState.frame = GetFrame();
-
-    nsRefPtr<nsAccessible> prevAcc;
-    PRInt32 childCount = 0;
-    walker.GetFirstChild();
-    SetFirstChild(walker.mState.accessible);
-
-    while (walker.mState.accessible) {
-      ++ childCount;
-      prevAcc = nsAccUtils::QueryAccessible(walker.mState.accessible);
-      prevAcc->SetParent(this);
-      walker.GetNextSibling();
-      prevAcc->SetNextSibling(walker.mState.accessible);
-    }
-    mAccChildCount = childCount;
-  }
-}
-
 PRBool
 nsAccessible::GetAllowsAnonChildAccessibles()
 {
   return PR_TRUE;
 }
 
 /* readonly attribute long childCount; */
-NS_IMETHODIMP nsAccessible::GetChildCount(PRInt32 *aAccChildCount) 
+NS_IMETHODIMP
+nsAccessible::GetChildCount(PRInt32 *aChildCount) 
 {
-  CacheChildren();
-  *aAccChildCount = mAccChildCount;
-  return NS_OK;  
+  NS_ENSURE_ARG_POINTER(aChildCount);
+
+  *aChildCount = GetChildCount();
+  return *aChildCount != -1 ? NS_OK : NS_ERROR_FAILURE;  
 }
 
 /* readonly attribute long indexInParent; */
-NS_IMETHODIMP nsAccessible::GetIndexInParent(PRInt32 *aIndexInParent)
+NS_IMETHODIMP
+nsAccessible::GetIndexInParent(PRInt32 *aIndexInParent)
 {
-  *aIndexInParent = -1;
-  if (!mWeakShell) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIAccessible> parent;
-  GetParent(getter_AddRefs(parent));
-  if (!parent) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIAccessible> sibling;
-  parent->GetFirstChild(getter_AddRefs(sibling));
-  if (!sibling) {
-    return NS_ERROR_FAILURE;
-  }
-
-  *aIndexInParent = 0;
-  while (sibling != this) {
-    NS_ASSERTION(sibling, "Never ran into the same child that we started from");
-
-    if (!sibling)
-      return NS_ERROR_FAILURE;
-
-    ++*aIndexInParent;
-    nsCOMPtr<nsIAccessible> tempAccessible;
-    sibling->GetNextSibling(getter_AddRefs(tempAccessible));
-    sibling = tempAccessible;
-  }
-
-  return NS_OK;
-}
-
-void
-nsAccessible::TestChildCache(nsIAccessible *aCachedChild)
-{
-#ifdef DEBUG_A11Y
-  // All cached accessible nodes should be in the parent
-  // It will assert if not all the children were created
-  // when they were first cached, and no invalidation
-  // ever corrected parent accessible's child cache.
-  if (mAccChildCount <= 0)
-    return;
-
-  nsCOMPtr<nsIAccessible> sibling = mFirstChild;
-
-  while (sibling != aCachedChild) {
-    NS_ASSERTION(sibling, "[TestChildCache] Never ran into the same child that we started from");
-    if (!sibling)
-      return;
-
-    nsCOMPtr<nsIAccessible> tempAccessible;
-    sibling->GetNextSibling(getter_AddRefs(tempAccessible));
-    sibling = tempAccessible;
-  }
-
-#endif
+  NS_ENSURE_ARG_POINTER(aIndexInParent);
+
+  *aIndexInParent = GetIndexInParent();
+  return *aIndexInParent != -1 ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult nsAccessible::GetTranslatedString(const nsAString& aKey, nsAString& aStringOut)
 {
   nsXPIDLString xsValue;
 
   if (!gStringBundle || 
     NS_FAILED(gStringBundle->GetStringFromName(PromiseFlatString(aKey).get(), getter_Copies(xsValue)))) 
@@ -1379,17 +1174,17 @@ NS_IMETHODIMP nsAccessible::SetSelected(
   // Add or remove selection
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;
   }
 
   PRUint32 state = nsAccUtils::State(this);
   if (state & nsIAccessibleStates::STATE_SELECTABLE) {
     nsCOMPtr<nsIAccessible> multiSelect =
-      nsAccUtils::GetMultiSelectFor(mDOMNode);
+      nsAccUtils::GetMultiSelectableContainer(mDOMNode);
     if (!multiSelect) {
       return aSelect ? TakeFocus() : NS_ERROR_FAILURE;
     }
     nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
     NS_ASSERTION(content, "Called for dead accessible");
 
     if (mRoleMapEntry) {
       if (aSelect) {
@@ -1409,17 +1204,17 @@ NS_IMETHODIMP nsAccessible::TakeSelectio
   // Select only this item
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;
   }
 
   PRUint32 state = nsAccUtils::State(this);
   if (state & nsIAccessibleStates::STATE_SELECTABLE) {
     nsCOMPtr<nsIAccessible> multiSelect =
-      nsAccUtils::GetMultiSelectFor(mDOMNode);
+      nsAccUtils::GetMultiSelectableContainer(mDOMNode);
     if (multiSelect) {
       nsCOMPtr<nsIAccessibleSelectable> selectable = do_QueryInterface(multiSelect);
       selectable->ClearSelection();
     }
     return SetSelected(PR_TRUE);
   }
 
   return NS_ERROR_FAILURE;
@@ -3108,18 +2903,257 @@ nsAccessible::GetNameInternal(nsAString&
     return GetHTMLName(aName);
 
   if (content->IsXUL())
     return GetXULName(aName);
 
   return NS_OK;
 }
 
+void
+nsAccessible::SetParent(nsIAccessible *aParent)
+{
+  NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
+
+  if (mParent && mParent != aParent) {
+    // Adopt a child -- we allow this now. the new parent
+    // may be a dom node which wasn't previously accessible but now is.
+    // The old parent's children now need to be invalidated, since 
+    // it no longer owns the child, the new parent does
+    NS_ASSERTION(PR_FALSE, "Adopting child!");
+    nsRefPtr<nsAccessible> oldParent = nsAccUtils::QueryAccessible(mParent);
+    if (oldParent)
+      oldParent->InvalidateChildren();
+  }
+
+  mParent = aParent;
+}
+
+void
+nsAccessible::InvalidateChildren()
+{
+  PRInt32 childCount = mChildren.Count();
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsRefPtr<nsAccessible> child =
+      nsAccUtils::QueryObject<nsAccessible>(mChildren.ObjectAt(childIdx));
+    child->mParent = nsnull;
+  }
+
+  mChildren.Clear();
+  mAreChildrenInitialized = PR_FALSE;
+}
+
+nsIAccessible*
+nsAccessible::GetParent()
+{
+  if (IsDefunct())
+    return nsnull;
+
+  if (mParent)
+    return mParent;
+
+  nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
+  NS_ASSERTION(docAccessible, "No document accessible for valid accessible!");
+
+  if (!docAccessible)
+    return nsnull;
+
+  nsCOMPtr<nsIAccessible> parent;
+  docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE,
+                                            getter_AddRefs(parent));
+
+#ifdef DEBUG
+  nsRefPtr<nsAccessible> parentAcc = nsAccUtils::QueryAccessible(parent);
+  NS_ASSERTION(!parentAcc->IsDefunct(), "Defunct parent!");
+
+  parentAcc->EnsureChildren();
+  if (parent != mParent)
+    NS_WARNING("Bad accessible tree!");
+#endif
+
+  return parent;
+}
+
+nsIAccessible*
+nsAccessible::GetChildAt(PRUint32 aIndex)
+{
+  if (EnsureChildren())
+    return nsnull;
+
+  nsIAccessible *child = mChildren.SafeObjectAt(aIndex);
+  if (!child)
+    return nsnull;
+
+#ifdef DEBUG
+  nsRefPtr<nsAccessible> childAcc = nsAccUtils::QueryAccessible(child);
+  nsCOMPtr<nsIAccessible> realParent = childAcc->mParent;
+  NS_ASSERTION(!realParent || realParent == this,
+               "Two accessibles have the same first child accessible!");
+#endif
+
+  return child;
+}
+
+PRInt32
+nsAccessible::GetChildCount()
+{
+  return EnsureChildren() ? -1 : mChildren.Count();
+}
+
+PRInt32
+nsAccessible::GetIndexOf(nsIAccessible *aChild)
+{
+  return EnsureChildren() ? -1 : mChildren.IndexOf(aChild);
+}
+
+PRInt32
+nsAccessible::GetIndexInParent()
+{
+  nsIAccessible *parent = GetParent();
+  if (!parent)
+    return -1;
+
+  nsRefPtr<nsAccessible> parentAcc =
+    nsAccUtils::QueryObject<nsAccessible>(parent);
+  return parentAcc->GetIndexOf(this);
+}
+
+already_AddRefed<nsIAccessible>
+nsAccessible::GetCachedParent()
+{
+  if (IsDefunct())
+    return nsnull;
+
+  nsCOMPtr<nsIAccessible> cachedParent = mParent;
+  return cachedParent.forget();
+}
+
+already_AddRefed<nsIAccessible>
+nsAccessible::GetCachedFirstChild()
+{
+  if (IsDefunct())
+    return nsnull;
+
+  nsCOMPtr<nsIAccessible> cachedFirstChild = GetChildAt(0);
+  return cachedFirstChild.forget();
+}
+
+
 ////////////////////////////////////////////////////////////////////////////////
-// nsAccessible private methods
+// nsAccessible protected methods
+
+void
+nsAccessible::CacheChildren()
+{
+  PRBool allowsAnonChildren = GetAllowsAnonChildAccessibles();
+  nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
+
+  // Seed the frame hint early while we're still on a container node.
+  // This is better than doing the GetPrimaryFrameFor() later on
+  // a text node, because text nodes aren't in the frame map.
+  walker.mState.frame = GetFrame();
+
+  walker.GetFirstChild();
+  while (walker.mState.accessible) {
+    mChildren.AppendObject(walker.mState.accessible);
+
+    nsRefPtr<nsAccessible> acc =
+      nsAccUtils::QueryObject<nsAccessible>(walker.mState.accessible);
+    acc->SetParent(this);
+
+    walker.GetNextSibling();
+  }
+}
+
+void
+nsAccessible::TestChildCache(nsIAccessible *aCachedChild)
+{
+#ifdef DEBUG_A11Y
+  // All cached accessible nodes should be in the parent
+  // It will assert if not all the children were created
+  // when they were first cached, and no invalidation
+  // ever corrected parent accessible's child cache.
+  PRUint32 childCount = mChildren.Count();
+  if (childCount == 0) {
+    NS_ASSERTION(mAreChildrenInitialized,
+                 "Children are stored but not initailzied!");
+    return;
+  }
+
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsIAccessible *child = GetChildAt(childIdx);
+    if (child == aCachedChild)
+      break;
+  }
+
+  NS_ASSERTION(child == aCachedChild,
+               "[TestChildCache] cached accessible wasn't found. Wrong accessible tree!");  
+#endif
+}
+
+PRBool
+nsAccessible::EnsureChildren()
+{
+  if (IsDefunct()) {
+    mAreChildrenInitialized = PR_FALSE;
+    return PR_TRUE;
+  }
+
+  if (mAreChildrenInitialized)
+    return PR_FALSE;
+
+  mAreChildrenInitialized = PR_TRUE; // Prevent reentry
+  CacheChildren();
+
+  return PR_FALSE;
+}
+
+nsIAccessible*
+nsAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError)
+{
+  if (IsDefunct()) {
+    if (aError)
+      *aError = NS_ERROR_FAILURE;
+
+    return nsnull;
+  }
+
+  nsIAccessible *parent = GetParent();
+  if (!parent) {
+    if (aError)
+      *aError = NS_ERROR_UNEXPECTED;
+
+    return nsnull;
+  }
+
+  nsRefPtr<nsAccessible> parentAcc =
+    nsAccUtils::QueryObject<nsAccessible>(parent);
+
+  PRInt32 indexInParent = parentAcc->GetIndexOf(this);
+  if (indexInParent == -1) {
+    if (aError)
+      *aError = NS_ERROR_UNEXPECTED;
+
+    return nsnull;
+  }
+
+  if (aError) {
+    PRInt32 childCount = parentAcc->GetChildCount();
+    if (indexInParent + aOffset >= childCount) {
+      *aError = NS_OK; // fail peacefully
+      return nsnull;
+    }
+  }
+
+  nsIAccessible *child = parentAcc->GetChildAt(indexInParent + aOffset);
+  if (aError && !child)
+    *aError = NS_ERROR_UNEXPECTED;
+
+  return child;
+}
 
 already_AddRefed<nsIAccessible>
 nsAccessible::GetFirstAvailableAccessible(nsIDOMNode *aStartNode)
 {
   nsIAccessibilityService *accService = GetAccService();
   nsCOMPtr<nsIAccessible> accessible;
   nsCOMPtr<nsIDOMTreeWalker> walker; 
   nsCOMPtr<nsIDOMNode> currentNode(aStartNode);
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -98,21 +98,21 @@ public:
   }
 
 private:
   nsTArray<nsString> mNames;
 };
 
 
 #define NS_ACCESSIBLE_IMPL_CID                          \
-{  /* 53cfa871-be42-47fc-b416-0033653b3151 */           \
-  0x53cfa871,                                           \
-  0xbe42,                                               \
-  0x47fc,                                               \
-  { 0xb4, 0x16, 0x00, 0x33, 0x65, 0x3b, 0x31, 0x51 }    \
+{  /* 07c5a6d6-4e87-4b57-8613-4c39e1b5150a */           \
+  0x07c5a6d6,                                           \
+  0x4e87,                                               \
+  0x4b57,                                               \
+  { 0x86, 0x13, 0x4c, 0x39, 0xe1, 0xb5, 0x15, 0x0a }    \
 }
 
 class nsAccessible : public nsAccessNodeWrap, 
                      public nsIAccessible, 
                      public nsIAccessibleHyperLink,
                      public nsIAccessibleSelectable,
                      public nsIAccessibleValue
 {
@@ -194,64 +194,79 @@ public:
    * @param  aDeepestChild  [in] flag points if deep child should be returned
    * @param  aChild         [out] found child
    */
   virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                    PRBool aDeepestChild,
                                    nsIAccessible **aChild);
 
   //////////////////////////////////////////////////////////////////////////////
-  // Initializing and cache methods
-
-  /**
-   * Set accessible parent.
-   */
-  void SetParent(nsIAccessible *aParent);
-
-  /**
-   * Set first accessible child.
-   */
-  void SetFirstChild(nsIAccessible *aFirstChild);
-
-  /**
-   * Set next sibling accessible.
-   */
-  void SetNextSibling(nsIAccessible *aNextSibling);
+  // 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 
    *                      nsnull if none.
    */
   virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry);
 
   /**
-   * Set the child count to -1 (unknown) and null out cached child pointers
+   * Set accessible parent.
+   */
+  void SetParent(nsIAccessible *aParent);
+
+  /**
+   * Set the child count to -1 (unknown) and null out cached child pointers.
+   * Should be called when accessible tree is changed because document has
+   * transformed.
    */
   virtual void InvalidateChildren();
 
+  //////////////////////////////////////////////////////////////////////////////
+  // Accessible tree traverse methods
+
+  /**
+   * Return parent accessible.
+   */
+  virtual nsIAccessible* GetParent();
+
+  /**
+   * Return child accessible at the given index.
+   */
+  virtual nsIAccessible* GetChildAt(PRUint32 aIndex);
+
+  /**
+   * Return child accessible count.
+   */
+  virtual PRInt32 GetChildCount();
+
+  /**
+   * Return index of the given child accessible.
+   */
+  virtual PRInt32 GetIndexOf(nsIAccessible *aChild);
+
+  /**
+   * Return index in parent accessible.
+   */
+  PRInt32 GetIndexInParent();
+
   /**
    * Return parent accessible only if cached.
    */
   already_AddRefed<nsIAccessible> GetCachedParent();
 
   /**
    * Return first child accessible only if cached.
    */
   already_AddRefed<nsIAccessible> GetCachedFirstChild();
 
-  /**
-   * Assert if child not in parent's cache.
-   */
-  void TestChildCache(nsIAccessible *aCachedChild);
-
   //////////////////////////////////////////////////////////////////////////////
-  // Miscellaneous methods.
+  // Miscellaneous methods
 
   /**
    * Fire accessible event.
    */
   virtual nsresult FireAccessibleEvent(nsIAccessibleEvent *aAccEvent);
 
   /**
    * Return true if there are accessible children in anonymous content
@@ -264,66 +279,66 @@ public:
    *
    * @param aText         returned text of the accessible
    * @param aStartOffset  start offset inside of the accesible
    * @param aLength       required lenght of text
    */
   virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
                                 PRUint32 aLength);
 
+protected:
+
   //////////////////////////////////////////////////////////////////////////////
-  // Helper methods
-  
-  already_AddRefed<nsIAccessible> GetParent() {
-    nsIAccessible *parent = nsnull;
-    GetParent(&parent);
-    return parent;
-  }
+  // Initializing, cache and tree traverse methods
+
+  /**
+   * Cache accessible children.
+   */
+  virtual void CacheChildren();
+
+  /**
+   * Assert if child not in parent's cache.
+   */
+  void TestChildCache(nsIAccessible *aCachedChild);
 
-protected:
+  /**
+   * Cache children if necessary. Return true if the accessible is defunct.
+   */
+  PRBool EnsureChildren();
+
+  /**
+   * Return sibling accessible at the given offset.
+   */
+  virtual nsIAccessible* GetSiblingAtOffset(PRInt32 aOffset,
+                                            nsresult* aError = nsnull);
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Miscellaneous helpers
+
   virtual nsIFrame* GetBoundsFrame();
   virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
   PRBool IsVisible(PRBool *aIsOffscreen); 
 
   //////////////////////////////////////////////////////////////////////////////
-  // Name helpers.
+  // Name helpers
 
   /**
    * Compute the name of HTML node.
    */
   nsresult GetHTMLName(nsAString& aName);
 
   /**
    * Compute the name for XUL node.
    */
   nsresult GetXULName(nsAString& aName);
 
   // helper method to verify frames
   static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
   static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
 
-  /**
-   * Walk into subtree and calculate the string which is used as the accessible
-   * name or description.
-   *
-   * @param aContent      [in] traversed content
-   * @param aFlatString   [in, out] result string
-   * @param aIsRootHidden [in] specifies whether root content (we started to
-   *                      traverse from) is hidden, in this case the result
-   *                      string is calculated from hidden children
-   *                      (this is used when hidden root content is explicitly
-   *                      specified as label or description by author)
-   */
-  nsresult AppendFlatStringFromSubtreeRecurse(nsIContent *aContent,
-                                              nsAString *aFlatString,
-                                              PRBool aIsRootHidden);
-
-  // Helpers for dealing with children
-  virtual void CacheChildren();
-  
   // nsCOMPtr<>& is useful here, because getter_AddRefs() nulls the comptr's value, and NextChild
   // depends on the passed-in comptr being null or already set to a child (finding the next sibling).
   nsIAccessible *NextChild(nsCOMPtr<nsIAccessible>& aAccessible);
     
   already_AddRefed<nsIAccessible> GetNextWithState(nsIAccessible *aStart, PRUint32 matchState);
 
   /**
    * Return an accessible for the given DOM node, or if that node isn't
@@ -431,20 +446,19 @@ protected:
    * in xul:tree accessible to lie to AT. Must be overridden in wrap classes.
    *
    * @param aEvent  the accessible event to fire.
    */
   virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent) = 0;
 
   // Data Members
   nsCOMPtr<nsIAccessible> mParent;
-  nsCOMPtr<nsIAccessible> mFirstChild;
-  nsCOMPtr<nsIAccessible> mNextSibling;
+  nsCOMArray<nsIAccessible> mChildren;
+  PRBool mAreChildrenInitialized;
 
   nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
-  PRInt32 mAccChildCount;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessible,
                               NS_ACCESSIBLE_IMPL_CID)
 
 #endif  
 
--- a/accessible/src/base/nsAccessibleTreeWalker.cpp
+++ b/accessible/src/base/nsAccessibleTreeWalker.cpp
@@ -72,17 +72,17 @@ nsAccessibleTreeWalker::~nsAccessibleTre
 
 void nsAccessibleTreeWalker::GetKids(nsIDOMNode *aParentNode)
 {
   nsCOMPtr<nsIContent> parentContent(do_QueryInterface(aParentNode));
   if (!parentContent || !parentContent->IsHTML()) {
     mState.frame = nsnull;  // Don't walk frames in non-HTML content, just walk the DOM.
   }
 
-  UpdateFrame(PR_TRUE);
+  WalkFrames();
 
   // Walk frames? UpdateFrame() sets this when it sees anonymous frames
   if (mState.siblingIndex == eSiblingsWalkFrames) {
     return;
   }
 
   // Walk anonymous content? Not currently used for HTML -- anonymous content there uses frame walking
   mState.siblingIndex = 0;   // Indicates our index into the sibling list
@@ -155,42 +155,61 @@ NS_IMETHODIMP nsAccessibleTreeWalker::Pu
   *nextToLastState = mState;  // Deep copy - copy contents of struct to new state that will be added to end of our stack
   ClearState();
   mState.prevState = nextToLastState;   // Link to previous state
   return NS_OK;
 }
 
 void nsAccessibleTreeWalker::GetNextDOMNode()
 {
-  // Get next DOM node
+  // Get next DOM node and its frame.
   if (mState.parentContent) {
-    mState.domNode = do_QueryInterface(mState.parentContent->GetChildAt(++mState.siblingIndex));
+    mState.domNode =
+      do_QueryInterface(mState.parentContent->GetChildAt(++mState.siblingIndex));
+
+  } else if (mState.siblingIndex == eSiblingsWalkFrames) {
+    if (mState.frame.IsAlive()) {
+      mState.frame = mState.frame.GetFrame()->GetNextSibling();
+
+      if (mState.frame.IsAlive()) {
+        mState.domNode = do_QueryInterface(mState.frame.GetFrame()->GetContent());
+        return;
+      }
+    }
+
+    mState.domNode = nsnull;
+    return;
+
+  } else {
+    mState.siblingList->Item(++mState.siblingIndex,
+                             getter_AddRefs(mState.domNode));
   }
-  else if (mState.siblingIndex == eSiblingsWalkFrames) {
-    if (mState.frame.GetFrame()) {
-      mState.domNode = do_QueryInterface(mState.frame.GetFrame()->GetContent());
-    } else {
-      mState.domNode = nsnull;
-    }
-  }
-  else { 
-    mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(mState.domNode));
-  }
+
+  // Update the frame.
+  nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
+  NS_ASSERTION(presShell, "Huh? No presshell?");
+  if (!presShell)
+    return;
+
+  nsCOMPtr<nsIContent> content = do_QueryInterface(mState.domNode);
+  if (content)
+    mState.frame = presShell->GetRealPrimaryFrameFor(content);
+  else
+    mState.frame = presShell->GetRootFrame();
 }
 
 NS_IMETHODIMP nsAccessibleTreeWalker::GetNextSibling()
 {
   // Make sure mState.prevState and mState.siblingIndex are initialized so we can walk forward
   NS_ASSERTION(mState.prevState && mState.siblingIndex != eSiblingsUninitialized,
                "Error - GetNextSibling() only works after a GetFirstChild(), so we must have a prevState.");
   mState.accessible = nsnull;
 
   while (PR_TRUE) {
     // Get next frame
-    UpdateFrame(PR_FALSE);
     GetNextDOMNode();
 
     if (!mState.domNode) {  // Done with current siblings
       PopState();   // Use parent - go up in stack. Can always pop state because we have to start with a GetFirstChild().
       if (!mState.prevState) {
         mState.accessible = nsnull;
         break; // Back to original accessible that we did GetFirstChild() from
       }
@@ -214,83 +233,78 @@ NS_IMETHODIMP nsAccessibleTreeWalker::Ge
 
   PushState();
   GetKids(parent); // Side effects change our state (mState)
 
   // Recursive loop: depth first search for first accessible child
   while (mState.domNode) {
     if ((mState.domNode != parent && GetAccessible()) || NS_SUCCEEDED(GetFirstChild()))
       return NS_OK;
-    UpdateFrame(PR_FALSE);
+
     GetNextDOMNode();
   }
 
   PopState();  // Return to previous state
   return NS_ERROR_FAILURE;
 }
 
-void nsAccessibleTreeWalker::UpdateFrame(PRBool aTryFirstChild)
+void 
+nsAccessibleTreeWalker::WalkFrames()
 {
   nsIFrame *curFrame = mState.frame.GetFrame();
   if (!curFrame) {
     return;
   }
 
-  if (aTryFirstChild) {
-    // If the frame implements nsIAnonymousContentCreator interface then go down
-    // through the frames and obtain anonymous nodes for them.
-    nsIAnonymousContentCreator* creator = do_QueryFrame(curFrame);
-    nsIFrame *child = curFrame->GetFirstChild(nsnull);
+  // If the frame implements nsIAnonymousContentCreator interface then go down
+  // through the frames and obtain anonymous nodes for them.
+  nsIAnonymousContentCreator* creator = do_QueryFrame(curFrame);
+  nsIFrame *child = curFrame->GetFirstChild(nsnull);
+
+  if (creator && child && mState.siblingIndex < 0) {
     mState.frame = child;
-
-    if (creator && child && mState.siblingIndex < 0) {
-      mState.domNode = do_QueryInterface(child->GetContent());
-      mState.siblingIndex = eSiblingsWalkFrames;
-    }
+    mState.domNode = do_QueryInterface(child->GetContent());
+    mState.siblingIndex = eSiblingsWalkFrames;
+  }
 // temporary workaround for Bug 359210. We never want to walk frames.
 // Aaron Leventhal will refix :before and :after content later without walking frames.
 #if 0
-    if (mState.frame && mState.siblingIndex < 0) {
-      // Container frames can contain generated content frames from
-      // :before and :after style rules, so we walk their frame trees
-      // instead of content trees
-      // XXX Walking the frame tree doesn't get us Aural CSS nodes, e.g. 
-      // @media screen { display: none; }
-      // Asking the style system might be better (with ProbePseudoStyleFor(),
-      // except that we need to ask only for those display types that support 
-      // :before and :after (which roughly means non-replaced elements)
-      // Here's some code to see if there is an :after rule for an element
-      // nsRefPtr<nsStyleContext> pseudoContext;
-      // nsStyleContext *styleContext = primaryFrame->GetStyleContext();
-      // if (aContent) {
-      //   pseudoContext = presContext->StyleSet()->
-      //     ProbePseudoStyleFor(content, nsAccessibilityAtoms::after, aStyleContext);
-      mState.domNode = do_QueryInterface(mState.frame->GetContent());
-      mState.siblingIndex = eSiblingsWalkFrames;
-    }
+  if (mState.frame && mState.siblingIndex < 0) {
+    // Container frames can contain generated content frames from
+    // :before and :after style rules, so we walk their frame trees
+    // instead of content trees
+    // XXX Walking the frame tree doesn't get us Aural CSS nodes, e.g. 
+    // @media screen { display: none; }
+    // Asking the style system might be better (with ProbePseudoStyleFor(),
+    // except that we need to ask only for those display types that support 
+    // :before and :after (which roughly means non-replaced elements)
+    // Here's some code to see if there is an :after rule for an element
+    // nsRefPtr<nsStyleContext> pseudoContext;
+    // nsStyleContext *styleContext = primaryFrame->GetStyleContext();
+    // if (aContent) {
+    //   pseudoContext = presContext->StyleSet()->
+    //     ProbePseudoStyleFor(content, nsAccessibilityAtoms::after, aStyleContext);
+    mState.domNode = do_QueryInterface(mState.frame->GetContent());
+    mState.siblingIndex = eSiblingsWalkFrames;
+  }
 #endif
-  }
-  else {
-    mState.frame = curFrame->GetNextSibling();
-  }
 }
 
 /**
  * If the DOM node's frame has an accessible or the DOMNode
  * itself implements nsIAccessible return it.
  */
 PRBool nsAccessibleTreeWalker::GetAccessible()
 {
   if (!mAccService) {
     return PR_FALSE;
   }
 
   mState.accessible = nsnull;
   nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
 
-  nsIFrame *frame = mState.frame.GetFrame();
   mAccService->GetAccessible(mState.domNode, presShell, mWeakShell,
-                             &frame, &mState.isHidden,
+                             mState.frame.GetFrame(), &mState.isHidden,
                              getter_AddRefs(mState.accessible));
-  mState.frame = frame;
+
   return mState.accessible ? PR_TRUE : PR_FALSE;
 }
 
--- a/accessible/src/base/nsAccessibleTreeWalker.h
+++ b/accessible/src/base/nsAccessibleTreeWalker.h
@@ -116,22 +116,19 @@ protected:
   NS_IMETHOD PushState();
 
   /**
    * Pop state from stack and make it current.
    */
   NS_IMETHOD PopState();
 
   /**
-   * Change current state so that its frame is changed to next frame.
-   *
-   * @param  aTryFirstChild  [in] points whether we should move to child or
-   *                         sibling frame
+   * Make treewalker traverse by frame tree if necessary.
    */
-  void UpdateFrame(PRBool aTryFirstChild);
+  void WalkFrames();
 
   /**
    * Change current state so that its node is changed to next node.
    */
   void GetNextDOMNode();
 
   nsCOMPtr<nsIWeakReference> mWeakShell;
   nsCOMPtr<nsIAccessibilityService> mAccService;
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -37,74 +37,32 @@
  * 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 "nsAccessibilityService.h"
+
 #include "nsIComponentManager.h"
 #include "nsServiceManagerUtils.h"
 
-nsApplicationAccessible::nsApplicationAccessible():
-    nsAccessibleWrap(nsnull, nsnull), mChildren(nsnull)
+nsApplicationAccessible::nsApplicationAccessible() :
+  nsAccessibleWrap(nsnull, nsnull)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsApplicationAccessible)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsApplicationAccessible,
-                                                  nsAccessible)
-
-  nsCOMPtr<nsISimpleEnumerator> enumerator;
-  tmp->mChildren->Enumerate(getter_AddRefs(enumerator));
-
-  nsCOMPtr<nsIWeakReference> childWeakRef;
-  nsCOMPtr<nsIAccessible> accessible;
-
-  PRBool hasMoreElements;
-  while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements))
-        && hasMoreElements) {
-
-    enumerator->GetNext(getter_AddRefs(childWeakRef));
-    accessible = do_QueryReferent(childWeakRef);
-    if (accessible) {
-      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "nsApplicationAccessible child");
-      cb.NoteXPCOMChild(accessible);
-    }
-  }
-  
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsApplicationAccessible,
-                                                nsAccessible)
-  tmp->mChildren->Clear();
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsApplicationAccessible)
-NS_INTERFACE_MAP_END_INHERITING(nsAccessible)
-
-NS_IMPL_ADDREF_INHERITED(nsApplicationAccessible, nsAccessible)
-NS_IMPL_RELEASE_INHERITED(nsApplicationAccessible, nsAccessible)
+NS_IMPL_ISUPPORTS_INHERITED0(nsApplicationAccessible, nsAccessible)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsIAccessNode
-
-nsresult
-nsApplicationAccessible::Init()
-{
-  nsresult rv;
-  mChildren = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
-  return rv;
-}
-
 // nsIAccessible
 
 NS_IMETHODIMP
 nsApplicationAccessible::GetName(nsAString& aName)
 {
   aName.Truncate();
 
   nsCOMPtr<nsIStringBundleService> bundleService =
@@ -125,172 +83,146 @@ nsApplicationAccessible::GetName(nsAStri
     NS_WARNING("brandShortName not found, using default app name");
     appName.AssignLiteral("Gecko based application");
   }
 
   aName.Assign(appName);
   return NS_OK;
 }
 
-nsresult
-nsApplicationAccessible::GetRoleInternal(PRUint32 *aRole)
+NS_IMETHODIMP
+nsApplicationAccessible::GetDescription(nsAString& aValue)
 {
-  *aRole = nsIAccessibleRole::ROLE_APP_ROOT;
+  aValue.Truncate();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsApplicationAccessible::GetRole(PRUint32 *aRole)
 {
+  NS_ENSURE_ARG_POINTER(aRole);
+
   return GetRoleInternal(aRole);
 }
 
+NS_IMETHODIMP
+nsApplicationAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
+{
+  NS_ENSURE_ARG_POINTER(aState);
+  *aState = 0;
+
+  if (aExtraState)
+    *aExtraState = 0;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetParent(nsIAccessible **aAccessible)
+{
+  NS_ENSURE_ARG_POINTER(aAccessible);
+  *aAccessible = nsnull;
+
+  return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessNode public methods
+
+PRBool
+nsApplicationAccessible::IsDefunct()
+{
+  return nsAccessibilityService::gIsShutdown;
+}
+
+nsresult
+nsApplicationAccessible::Init()
+{
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessible public methods
+
+nsresult
+nsApplicationAccessible::GetRoleInternal(PRUint32 *aRole)
+{
+  *aRole = nsIAccessibleRole::ROLE_APP_ROOT;
+  return NS_OK;
+}
+
 nsresult
 nsApplicationAccessible::GetStateInternal(PRUint32 *aState,
                                           PRUint32 *aExtraState)
 {
   *aState = 0;
   if (aExtraState)
     *aExtraState = 0;
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsApplicationAccessible::GetParent(nsIAccessible **aParent)
+nsIAccessible*
+nsApplicationAccessible::GetParent()
 {
-  *aParent = nsnull;
-  return NS_OK;
+  return nsnull;
 }
 
-NS_IMETHODIMP
-nsApplicationAccessible::GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild)
+void
+nsApplicationAccessible::InvalidateChildren()
 {
-  NS_ENSURE_ARG_POINTER(aChild);
-  *aChild = nsnull;
-
-  PRUint32 count = 0;
-  nsresult rv = NS_OK;
-
-  if (mChildren) {
-    rv = mChildren->GetLength(&count);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  if (aChildNum >= static_cast<PRInt32>(count) || count == 0)
-    return NS_ERROR_INVALID_ARG;
-
-  if (aChildNum < 0)
-    aChildNum = count - 1;
-
-  nsCOMPtr<nsIWeakReference> childWeakRef;
-  rv = mChildren->QueryElementAt(aChildNum, NS_GET_IID(nsIWeakReference),
-                                 getter_AddRefs(childWeakRef));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (childWeakRef) {
-    nsCOMPtr<nsIAccessible> childAcc(do_QueryReferent(childWeakRef));
-    NS_IF_ADDREF(*aChild = childAcc);
-  }
-
-  return NS_OK;
+  // Do nothing because application children are kept updated by
+  // AddRootAccessible() and RemoveRootAccessible() method calls.
 }
 
-NS_IMETHODIMP
-nsApplicationAccessible::GetNextSibling(nsIAccessible **aNextSibling)
-{
-  NS_ENSURE_ARG_POINTER(aNextSibling);
-
-  *aNextSibling = nsnull;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsApplicationAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling)
-{
-  NS_ENSURE_ARG_POINTER(aPreviousSibling);
-
-  *aPreviousSibling = nsnull;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsApplicationAccessible::GetIndexInParent(PRInt32 *aIndexInParent)
-{
-  NS_ENSURE_ARG_POINTER(aIndexInParent);
-
-  *aIndexInParent = -1;
-  return NS_OK;
-}
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessible protected methods
 
 void
 nsApplicationAccessible::CacheChildren()
 {
-  if (!mChildren) {
-    mAccChildCount = eChildCountUninitialized;
-    return;
+  // Nothing to do. Children are keeped up to dated by Add/RemoveRootAccessible
+  // method calls.
+}
+
+nsIAccessible*
+nsApplicationAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError)
+{
+  if (IsDefunct()) {
+    if (aError)
+      *aError = NS_ERROR_FAILURE;
+
+    return nsnull;
   }
 
-  if (mAccChildCount == eChildCountUninitialized) {
-    mAccChildCount = 0;// Prevent reentry
-    nsCOMPtr<nsISimpleEnumerator> enumerator;
-    mChildren->Enumerate(getter_AddRefs(enumerator));
-
-    nsCOMPtr<nsIWeakReference> childWeakRef;
-    nsCOMPtr<nsIAccessible> accessible;
-    nsRefPtr<nsAccessible> prevAcc;
-    PRBool hasMoreElements;
+  if (aError)
+    *aError = NS_OK; // fail peacefully
 
-    while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
-          hasMoreElements) {
-      enumerator->GetNext(getter_AddRefs(childWeakRef));
-      accessible = do_QueryReferent(childWeakRef);
-      if (accessible) {
-        if (prevAcc)
-          prevAcc->SetNextSibling(accessible);
-        else
-          SetFirstChild(accessible);
-
-        prevAcc = nsAccUtils::QueryAccessible(accessible);
-        prevAcc->SetParent(this);
-      }
-    }
-
-    PRUint32 count = 0;
-    mChildren->GetLength(&count);
-    mAccChildCount = static_cast<PRInt32>(count);
-  }
+  return nsnull;
 }
 
-// nsApplicationAccessible
+////////////////////////////////////////////////////////////////////////////////
+// Public methods
 
 nsresult
 nsApplicationAccessible::AddRootAccessible(nsIAccessible *aRootAccessible)
 {
   NS_ENSURE_ARG_POINTER(aRootAccessible);
 
-  // add by weak reference
-  nsresult rv = mChildren->AppendElement(aRootAccessible, PR_TRUE);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (!mChildren.AppendObject(aRootAccessible))
+    return NS_ERROR_FAILURE;
 
-  InvalidateChildren();
+  nsRefPtr<nsAccessible> rootAcc = nsAccUtils::QueryAccessible(aRootAccessible);
+  rootAcc->SetParent(this);
+
   return NS_OK;
 }
 
 nsresult
 nsApplicationAccessible::RemoveRootAccessible(nsIAccessible *aRootAccessible)
 {
   NS_ENSURE_ARG_POINTER(aRootAccessible);
 
-  PRUint32 index = 0;
-
-  // we must use weak ref to get the index
-  nsCOMPtr<nsIWeakReference> weakPtr = do_GetWeakReference(aRootAccessible);
-  nsresult rv = mChildren->IndexOf(0, weakPtr, &index);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = mChildren->RemoveElementAt(index);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  InvalidateChildren();
-  return NS_OK;
+  // It's not needed to void root accessible parent because this method is
+  // called on root accessible shutdown and its parent will be cleared
+  // properly.
+  return mChildren.RemoveObject(aRootAccessible) ? NS_OK : NS_ERROR_FAILURE;
 }
-
--- a/accessible/src/base/nsApplicationAccessible.h
+++ b/accessible/src/base/nsApplicationAccessible.h
@@ -58,40 +58,42 @@
 
 class nsApplicationAccessible: public nsAccessibleWrap
 {
 public:
   nsApplicationAccessible();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsApplicationAccessible,
-                                           nsAccessible)
-
-  // nsAccessNode
-  virtual nsresult Init();
 
   // nsIAccessible
-  NS_IMETHOD GetName(nsAString & aName);
+  NS_IMETHOD GetName(nsAString& aName);
+  NS_IMETHOD GetDescription(nsAString& aValue);
   NS_IMETHOD GetRole(PRUint32 *aRole);
-  NS_IMETHOD GetParent(nsIAccessible * *aParent);
-  NS_IMETHOD GetNextSibling(nsIAccessible * *aNextSibling);
-  NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
-  NS_IMETHOD GetIndexInParent(PRInt32 *aIndexInParent);
-  NS_IMETHOD GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild);
+  NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+
+  NS_IMETHOD GetParent(nsIAccessible **aAccessible);
+
+  // nsAccessNode
+  virtual PRBool IsDefunct();
+  virtual nsresult Init();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+  virtual nsIAccessible* GetParent();
+
+  virtual void InvalidateChildren();
 
   // nsApplicationAccessible
   virtual nsresult AddRootAccessible(nsIAccessible *aRootAccWrap);
   virtual nsresult RemoveRootAccessible(nsIAccessible *aRootAccWrap);
 
 protected:
+
   // nsAccessible
   virtual void CacheChildren();
-
-  nsCOMPtr<nsIMutableArray> mChildren;
+  virtual nsIAccessible* GetSiblingAtOffset(PRInt32 aOffset,
+                                            nsresult *aError = nsnull);
 };
 
 #endif
 
--- a/accessible/src/base/nsBaseWidgetAccessible.cpp
+++ b/accessible/src/base/nsBaseWidgetAccessible.cpp
@@ -60,33 +60,36 @@
 
 nsLeafAccessible::nsLeafAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
 nsAccessibleWrap(aNode, aShell)
 {
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsLeafAccessible, nsAccessible)
 
-// nsAccessible::GetChildAtPoint()
+////////////////////////////////////////////////////////////////////////////////
+// nsLeafAccessible: nsAccessible public
+
 nsresult
 nsLeafAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                   PRBool aDeepestChild,
                                   nsIAccessible **aChild)
 {
   // Don't walk into leaf accessibles.
   NS_ADDREF(*aChild = this);
   return NS_OK;
 }
 
-// nsAccessible::CacheChildren()
+////////////////////////////////////////////////////////////////////////////////
+// nsLeafAccessible: nsAccessible private
+
 void
 nsLeafAccessible::CacheChildren()
 {
   // No children for leaf accessible.
-  mAccChildCount = IsDefunct() ? eChildCountUninitialized : 0;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsLinkableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsLinkableAccessible::
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -1022,17 +1022,17 @@ nsCoreUtils::GetLastSensibleColumn(nsITr
   cols->GetLastColumn(getter_AddRefs(column));
   if (column && IsColumnHidden(column))
     return GetPreviousSensibleColumn(column);
 
   return column.forget();
 }
 
 PRUint32
-nsCoreUtils::GetSensiblecolumnCount(nsITreeBoxObject *aTree)
+nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree)
 {
   PRUint32 count = 0;
 
   nsCOMPtr<nsITreeColumns> cols;
   aTree->GetColumns(getter_AddRefs(cols));
   if (!cols)
     return count;
 
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -408,17 +408,17 @@ public:
    * Return last sensible column for the given tree box object.
    */
   static already_AddRefed<nsITreeColumn>
     GetLastSensibleColumn(nsITreeBoxObject *aTree);
 
   /**
    * Return sensible columns count for the given tree box object.
    */
-  static PRUint32 GetSensiblecolumnCount(nsITreeBoxObject *aTree);
+  static PRUint32 GetSensibleColumnCount(nsITreeBoxObject *aTree);
 
   /**
    * Return sensible column at the given index for the given tree box object.
    */
   static already_AddRefed<nsITreeColumn>
     GetSensibleColumnAt(nsITreeBoxObject *aTree, PRUint32 aIndex);
 
   /**
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -68,26 +68,26 @@
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
 #include "nsFocusManager.h"
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #endif
 
-//=============================//
-// nsDocAccessible  //
-//=============================//
+////////////////////////////////////////////////////////////////////////////////
+// Static member initialization
 
 PRUint32 nsDocAccessible::gLastFocusedAccessiblesState = 0;
 nsIAtom *nsDocAccessible::gLastFocusedFrameType = nsnull;
 
-//-----------------------------------------------------
-// construction
-//-----------------------------------------------------
+
+////////////////////////////////////////////////////////////////////////////////
+// Constructor/desctructor
+
 nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
   nsHyperTextAccessibleWrap(aDOMNode, aShell), mWnd(nsnull),
   mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE),
   mIsLoadCompleteFired(PR_FALSE), mInFlushPendingEvents(PR_FALSE),
   mFireEventTimerStarted(PR_FALSE)
 {
   // XXX aaronl should we use an algorithm for the initial cache size?
   mAccessNodeCache.Init(kDefaultCacheSize);
@@ -124,25 +124,23 @@ nsDocAccessible::nsDocAccessible(nsIDOMN
     PRUint32 busyFlags;
     docShell->GetBusyFlags(&busyFlags);
     if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) {
       mIsContentLoaded = PR_TRUE;                                               
     }
   }
 }
 
-//-----------------------------------------------------
-// destruction
-//-----------------------------------------------------
 nsDocAccessible::~nsDocAccessible()
 {
 }
 
+
 ////////////////////////////////////////////////////////////////////////////////
-// nsDocAccessible. nsISupports
+// nsISupports
 
 static PLDHashOperator
 ElementTraverser(const void *aKey, nsIAccessNode *aAccessNode,
                  void *aUserArg)
 {
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
 
@@ -177,16 +175,20 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleDocument)
 NS_INTERFACE_MAP_END_INHERITING(nsHyperTextAccessible)
 
 NS_IMPL_ADDREF_INHERITED(nsDocAccessible, nsHyperTextAccessible)
 NS_IMPL_RELEASE_INHERITED(nsDocAccessible, nsHyperTextAccessible)
 
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessible
+
 NS_IMETHODIMP
 nsDocAccessible::GetName(nsAString& aName)
 {
   nsresult rv = NS_OK;
   aName.Truncate();
   if (mParent) {
     rv = mParent->GetName(aName); // Allow owning iframe to override the name
   }
@@ -199,16 +201,17 @@ nsDocAccessible::GetName(nsAString& aNam
   }
   if (aName.IsEmpty()) {   // Last resort: use URL
     rv = GetURL(aName);
   }
 
   return rv;
 }
 
+// nsAccessible public method
 nsresult
 nsDocAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   *aRole = nsIAccessibleRole::ROLE_PANE; // Fall back
 
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
   if (docShellTreeItem) {
@@ -237,16 +240,17 @@ nsDocAccessible::GetRoleInternal(PRUint3
     else if (itemType == nsIDocShellTreeItem::typeContent) {
       *aRole = nsIAccessibleRole::ROLE_DOCUMENT;
     }
   }
 
   return NS_OK;
 }
 
+// nsAccessible public method
 void
 nsDocAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
 {
   NS_ASSERTION(mDocument, "No document during initialization!");
   if (!mDocument)
     return;
 
   mRoleMapEntry = aRoleMapEntry;
@@ -277,16 +281,17 @@ nsDocAccessible::GetDescription(nsAStrin
       GetTextEquivFromIDRefs(this, nsAccessibilityAtoms::aria_describedby,
                              description);
     aDescription = description;
   }
 
   return NS_OK;
 }
 
+// nsAccessible public method
 nsresult
 nsDocAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
 {
   nsresult rv = nsAccessible::GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
 
 #ifdef MOZ_XUL
   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
@@ -327,16 +332,17 @@ nsDocAccessible::GetStateInternal(PRUint
   }
   else if (aExtraState) {
     *aExtraState |= nsIAccessibleStates::EXT_STATE_EDITABLE;
   }
 
   return NS_OK;
 }
 
+// nsAccessible public method
 nsresult
 nsDocAccessible::GetARIAState(PRUint32 *aState, PRUint32 *aExtraState)
 {
   // Combine with states from outer doc
   NS_ENSURE_ARG_POINTER(aState);
   nsresult rv = nsAccessible::GetARIAState(aState, aExtraState);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -391,17 +397,19 @@ NS_IMETHODIMP nsDocAccessible::TakeFocus
       return fm->MoveFocus(document->GetWindow(), nsnull,
                            nsIFocusManager::MOVEFOCUS_ROOT, 0,
                            getter_AddRefs(newFocus));
     }
   }
   return NS_ERROR_FAILURE;
 }
 
-// ------- nsIAccessibleDocument Methods (5) ---------------
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleDocument
 
 NS_IMETHODIMP nsDocAccessible::GetURL(nsAString& aURL)
 {
   if (!mDocument) {
     return NS_ERROR_FAILURE; // Document has been shut down
   }
   nsCOMPtr<nsISupports> container = mDocument->GetContainer();
   nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
@@ -494,16 +502,17 @@ NS_IMETHODIMP nsDocAccessible::GetDocume
   if (domDoc) {
     NS_ADDREF(*aDOMDoc);
     return NS_OK;
   }
 
   return NS_ERROR_FAILURE;
 }
 
+// nsIAccessibleHyperText method
 NS_IMETHODIMP nsDocAccessible::GetAssociatedEditor(nsIEditor **aEditor)
 {
   NS_ENSURE_ARG_POINTER(aEditor);
   *aEditor = nsnull;
 
   if (!mDocument)
     return NS_ERROR_FAILURE;
 
@@ -552,16 +561,17 @@ NS_IMETHODIMP nsDocAccessible::GetCached
     nsRefPtr<nsAccessible> parentAcc(nsAccUtils::QueryAccessible(parent));
     if (parentAcc)
       parentAcc->TestChildCache(accessible);
   }
 #endif
   return NS_OK;
 }
 
+// nsDocAccessible public method
 void
 nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode)
 {
   // If there is an access node for the given unique ID then let's shutdown it.
   // The unique ID may be presented in the cache if originally we created
   // access node object and then we want to create accessible object when
   // DOM node is changed.
   nsCOMPtr<nsIAccessNode> accessNode;
@@ -569,62 +579,39 @@ nsDocAccessible::CacheAccessNode(void *a
   if (accessNode) {
     nsRefPtr<nsAccessNode> accNode = nsAccUtils::QueryAccessNode(accessNode);
     accNode->Shutdown();
   }
 
   PutCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode);
 }
 
+// nsDocAccessible public method
 void
 nsDocAccessible::RemoveAccessNodeFromCache(nsIAccessNode *aAccessNode)
 {
   if (!aAccessNode)
     return;
 
   void *uniqueID = nsnull;
   aAccessNode->GetUniqueID(&uniqueID);
   mAccessNodeCache.Remove(uniqueID);
 }
 
-NS_IMETHODIMP nsDocAccessible::GetParent(nsIAccessible **aParent)
-{
-  // Hook up our new accessible with our parent
-  *aParent = nsnull;
-  NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
-  if (!mParent) {
-    nsIDocument *parentDoc = mDocument->GetParentDocument();
-    NS_ENSURE_TRUE(parentDoc, NS_ERROR_FAILURE);
-    nsIContent *ownerContent = parentDoc->FindContentForSubDocument(mDocument);
-    nsCOMPtr<nsIDOMNode> ownerNode(do_QueryInterface(ownerContent));
-    if (ownerNode) {
-      nsCOMPtr<nsIAccessibilityService> accService =
-        do_GetService("@mozilla.org/accessibilityService;1");
-      if (accService) {
-        // XXX aaronl: ideally we would traverse the presshell chain
-        // Since there's no easy way to do that, we cheat and use
-        // the document hierarchy. GetAccessibleFor() is bad because
-        // it doesn't support our concept of multiple presshells per doc.
-        // It should be changed to use GetAccessibleInWeakShell()
-        accService->GetAccessibleFor(ownerNode, getter_AddRefs(mParent));
-      }
-    }
-  }
-  return mParent ? nsAccessible::GetParent(aParent) : NS_ERROR_FAILURE;
-}
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessNode
 
 nsresult
 nsDocAccessible::Init()
 {
   PutCacheEntry(gGlobalDocAccessibleCache, mDocument, this);
 
   AddEventListeners();
 
-  nsCOMPtr<nsIAccessible> parentAccessible;  // Ensure outer doc mParent accessible
-  GetParent(getter_AddRefs(parentAccessible));
+  GetParent(); // Ensure outer doc mParent accessible.
 
   nsresult rv = nsHyperTextAccessibleWrap::Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Fire reorder event to notify new accessible document has been created and
   // attached to the tree.
   nsCOMPtr<nsIAccessibleEvent> reorderEvent =
     new nsAccReorderEvent(mParent, PR_FALSE, PR_TRUE, mDOMNode);
@@ -675,16 +662,17 @@ nsDocAccessible::Shutdown()
   // can find the doc or root accessible in the cache if they need it.
   // We don't do this during ShutdownAccessibility() because that is already clearing the cache
   if (!nsAccessibilityService::gIsShutdown)
     gGlobalDocAccessibleCache.Remove(static_cast<void*>(kungFuDeathGripDoc));
 
   return NS_OK;
 }
 
+// nsDocAccessible protected member
 void nsDocAccessible::ShutdownChildDocuments(nsIDocShellTreeItem *aStart)
 {
   nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aStart));
   if (treeNode) {
     PRInt32 subDocuments;
     treeNode->GetChildCount(&subDocuments);
     for (PRInt32 count = 0; count < subDocuments; count ++) {
       nsCOMPtr<nsIDocShellTreeItem> treeItemChild;
@@ -720,16 +708,17 @@ PRBool
 nsDocAccessible::IsDefunct()
 {
   if (nsHyperTextAccessibleWrap::IsDefunct())
     return PR_TRUE;
 
   return !mDocument;
 }
 
+// nsDocAccessible protected member
 void nsDocAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aRelativeFrame)
 {
   *aRelativeFrame = GetFrame();
 
   nsIDocument *document = mDocument;
   nsIDocument *parentDoc = nsnull;
 
   while (document) {
@@ -763,17 +752,17 @@ void nsDocAccessible::GetBoundsRect(nsRe
     else {  // First time through loop
       aBounds = viewBounds;
     }
 
     document = parentDoc = document->GetParentDocument();
   }
 }
 
-
+// nsDocAccessible protected member
 nsresult nsDocAccessible::AddEventListeners()
 {
   // 1) Set up scroll position listener
   // 2) Check for editor and listen for changes to editor
 
   nsCOMPtr<nsIPresShell> presShell(GetPresShell());
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
@@ -809,16 +798,17 @@ nsresult nsDocAccessible::AddEventListen
     }
   }
 
   // add document observer
   mDocument->AddObserver(this);
   return NS_OK;
 }
 
+// nsDocAccessible protected member
 nsresult nsDocAccessible::RemoveEventListeners()
 {
   // Remove listeners associated with content documents
   // Remove scroll position listener
   RemoveScrollListener();
 
   NS_ASSERTION(mDocument, "No document during removal of listeners.");
 
@@ -855,16 +845,17 @@ nsresult nsDocAccessible::RemoveEventLis
       nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
       caretAccessible->RemoveDocSelectionListener(presShell);
     }
   }
 
   return NS_OK;
 }
 
+// nsDocAccessible public member
 void
 nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
 {
   if (IsDefunct())
     return;
 
   PRBool isFinished = 
              (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
@@ -884,18 +875,17 @@ nsDocAccessible::FireDocLoadEvents(PRUin
     return;
 
   nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
   treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
 
   if (isFinished) {
     // Need to wait until scrollable view is available
     AddScrollListener();
-    nsCOMPtr<nsIAccessible> parent(nsAccessible::GetParent());
-    nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(parent));
+    nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(GetParent()));
     if (acc) {
       // Make the parent forget about the old document as a child
       acc->InvalidateChildren();
     }
 
     if (sameTypeRoot != treeItem) {
       // Fire show/hide events to indicate frame/iframe content is new, rather than
       // doc load event which causes screen readers to act is if entire page is reloaded
@@ -949,48 +939,53 @@ void nsDocAccessible::ScrollTimerCallbac
     if (docAcc->mScrollWatchTimer) {
       docAcc->mScrollWatchTimer->Cancel();
       docAcc->mScrollWatchTimer = nsnull;
       NS_RELEASE(docAcc); // Release kung fu death grip
     }
   }
 }
 
+// nsDocAccessible protected member
 void nsDocAccessible::AddScrollListener()
 {
   nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
 
   nsIViewManager* vm = nsnull;
   if (presShell)
     vm = presShell->GetViewManager();
 
   nsIScrollableView* scrollableView = nsnull;
   if (vm)
     vm->GetRootScrollableView(&scrollableView);
 
   if (scrollableView)
     scrollableView->AddScrollPositionListener(this);
 }
 
+// nsDocAccessible protected member
 void nsDocAccessible::RemoveScrollListener()
 {
   nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
 
   nsIViewManager* vm = nsnull;
   if (presShell)
     vm = presShell->GetViewManager();
 
   nsIScrollableView* scrollableView = nsnull;
   if (vm)
     vm->GetRootScrollableView(&scrollableView);
 
   if (scrollableView)
     scrollableView->RemoveScrollPositionListener(this);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsIScrollPositionListener
+
 NS_IMETHODIMP nsDocAccessible::ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocAccessible::ScrollPositionDidChange(nsIScrollableView *aScrollableView, nscoord aX, nscoord aY)
 {
   // Start new timer, if the timer cycles at least 1 full cycle without more scroll position changes,
@@ -1007,31 +1002,34 @@ NS_IMETHODIMP nsDocAccessible::ScrollPos
                                               kScrollPosCheckWait,
                                               nsITimer::TYPE_REPEATING_SLACK);
     }
   }
   mScrollPositionChangedTicks = 1;
   return NS_OK;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsIObserver
+
 NS_IMETHODIMP nsDocAccessible::Observe(nsISupports *aSubject, const char *aTopic,
                                        const PRUnichar *aData)
 {
   if (!nsCRT::strcmp(aTopic,"obs_documentCreated")) {    
     // State editable will now be set, readonly is now clear
     nsCOMPtr<nsIAccessibleEvent> event =
       new nsAccStateChangeEvent(this, nsIAccessibleStates::EXT_STATE_EDITABLE,
                                 PR_TRUE, PR_TRUE);
     FireAccessibleEvent(event);
   }
 
   return NS_OK;
 }
 
-  ///////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
 // nsIDocumentObserver
 
 NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsDocAccessible)
 NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsDocAccessible)
 NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsDocAccessible)
 
 void
 nsDocAccessible::AttributeWillChange(nsIDocument *aDocument,
@@ -1042,32 +1040,32 @@ nsDocAccessible::AttributeWillChange(nsI
   // Here we will want to cache whatever state we are potentially interested in,
   // such as the existence of aria-pressed for button (so we know if we need to
   // newly expose it as a toggle button) etc.
 }
 
 void
 nsDocAccessible::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
                                   PRInt32 aNameSpaceID, nsIAtom* aAttribute,
-                                  PRInt32 aModType, PRUint32 aStateMask)
+                                  PRInt32 aModType)
 {
   AttributeChangedImpl(aContent, aNameSpaceID, aAttribute);
 
   // If it was the focused node, cache the new state
   nsCOMPtr<nsIDOMNode> targetNode = do_QueryInterface(aContent);
   if (targetNode == gLastFocusedNode) {
     nsCOMPtr<nsIAccessible> focusedAccessible;
     GetAccService()->GetAccessibleFor(targetNode, getter_AddRefs(focusedAccessible));
     if (focusedAccessible) {
       gLastFocusedAccessiblesState = nsAccUtils::State(focusedAccessible);
     }
   }
 }
 
-
+// nsDocAccessible protected member
 void
 nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID, nsIAtom* aAttribute)
 {
   // Fire accessible event after short timer, because we need to wait for
   // DOM attribute & resulting layout to actually change. Otherwise,
   // assistive technology will retrieve the wrong state/value/selection info.
 
   // XXX todo
@@ -1166,17 +1164,17 @@ nsDocAccessible::AttributeChangedImpl(ns
                                targetNode);
     return;
   }
 
   if (aAttribute == nsAccessibilityAtoms::selected ||
       aAttribute == nsAccessibilityAtoms::aria_selected) {
     // ARIA or XUL selection
     nsCOMPtr<nsIAccessible> multiSelect =
-      nsAccUtils::GetMultiSelectFor(targetNode);
+      nsAccUtils::GetMultiSelectableContainer(targetNode);
     // Multi selects use selection_add and selection_remove
     // Single select widgets just mirror event_selection for
     // whatever gets event_focus, which is done in
     // nsRootAccessible::FireAccessibleFocusEvent()
     // So right here we make sure only to deal with multi selects
     if (multiSelect) {
       // Need to find the right event to use here, SELECTION_WITHIN would
       // seem right but we had started using it for something else
@@ -1208,16 +1206,17 @@ nsDocAccessible::AttributeChangedImpl(ns
       new nsAccStateChangeEvent(targetNode,
                                 nsIAccessibleStates::EXT_STATE_EDITABLE,
                                 PR_TRUE);
     FireDelayedAccessibleEvent(editableChangeEvent);
     return;
   }
 }
 
+// nsDocAccessible protected member
 void
 nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
 {
   nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(aContent));
   if (!targetNode)
     return;
 
   if (aAttribute == nsAccessibilityAtoms::aria_required) {
@@ -1357,16 +1356,17 @@ void nsDocAccessible::ContentAppended(ns
     // InvalidateCacheSubtree will not fire the EVENT_SHOW for the new node
     // unless an accessible can be created for the passed in node, which it
     // can't do unless the node is visible. The right thing happens there so
     // no need for an extra visibility check here.
     InvalidateCacheSubtree(child, nsIAccessibilityService::NODE_APPEND);
   }
 }
 
+
 void nsDocAccessible::ContentStatesChanged(nsIDocument* aDocument,
                                            nsIContent* aContent1,
                                            nsIContent* aContent2,
                                            PRInt32 aStateMask)
 {
   if (0 == (aStateMask & NS_EVENT_STATE_CHECKED)) {
     return;
   }
@@ -1412,16 +1412,55 @@ nsDocAccessible::ContentRemoved(nsIDocum
   // the same subtree.
 }
 
 void
 nsDocAccessible::ParentChainChanged(nsIContent *aContent)
 {
 }
 
+
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessible
+
+nsIAccessible*
+nsDocAccessible::GetParent()
+{
+  if (IsDefunct())
+    return nsnull;
+
+  if (mParent)
+    return mParent;
+
+  nsIDocument* parentDoc = mDocument->GetParentDocument();
+  if (!parentDoc)
+    return nsnull;
+
+  nsIContent* ownerContent = parentDoc->FindContentForSubDocument(mDocument);
+  nsCOMPtr<nsIDOMNode> ownerNode(do_QueryInterface(ownerContent));
+  if (ownerNode) {
+    nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
+    if (accService) {
+      // XXX aaronl: ideally we would traverse the presshell chain. Since
+      // there's no easy way to do that, we cheat and use the document
+      // hierarchy. GetAccessibleFor() is bad because it doesn't support our
+      // concept of multiple presshells per doc.
+      // It should be changed to use GetAccessibleInWeakShell()
+      accService->GetAccessibleFor(ownerNode, getter_AddRefs(mParent));
+    }
+  }
+
+  NS_ASSERTION(mParent, "No parent for not root document accessible!");
+  return mParent;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Protected members
+
 void
 nsDocAccessible::FireValueChangeForTextFields(nsIAccessible *aPossibleTextFieldAccessible)
 {
   if (nsAccUtils::Role(aPossibleTextFieldAccessible) != nsIAccessibleRole::ROLE_ENTRY)
     return;
 
   // Dependent value change event for text changes in textfields
   nsCOMPtr<nsIAccessibleEvent> valueChangeEvent =
@@ -1566,30 +1605,32 @@ nsDocAccessible::CreateTextChangeEventFo
   }
 
   nsIAccessibleEvent *event =
     new nsAccTextChangeEvent(aContainerAccessible, offset, length, aIsInserting, aIsAsynch);
   NS_IF_ADDREF(event);
 
   return event;
 }
-  
+
+// nsDocAccessible public member
 nsresult
 nsDocAccessible::FireDelayedAccessibleEvent(PRUint32 aEventType,
                                             nsIDOMNode *aDOMNode,
                                             nsAccEvent::EEventRule aAllowDupes,
                                             PRBool aIsAsynch)
 {
   nsCOMPtr<nsIAccessibleEvent> event =
     new nsAccEvent(aEventType, aDOMNode, aIsAsynch, aAllowDupes);
   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
   return FireDelayedAccessibleEvent(event);
 }
 
+// nsDocAccessible public member
 nsresult
 nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
   NS_ENSURE_ARG(aEvent);
 
   nsRefPtr<nsAccEvent> accEvent = nsAccUtils::QueryObject<nsAccEvent>(aEvent);
   mEventsToFire.AppendElement(accEvent);
 
@@ -1948,16 +1989,17 @@ void nsDocAccessible::RefreshNodes(nsIDO
   accessNode->GetUniqueID(&uniqueID);
   nsRefPtr<nsAccessNode> accNode = nsAccUtils::QueryAccessNode(accessNode);
   accNode->Shutdown();
 
   // Remove from hash table as well
   mAccessNodeCache.Remove(uniqueID);
 }
 
+// nsDocAccessible public member
 void
 nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
                                         PRUint32 aChangeType)
 {
   PRBool isHiding =
     aChangeType == nsIAccessibilityService::FRAME_HIDE ||
     aChangeType == nsIAccessibilityService::NODE_REMOVE;
 
@@ -2175,16 +2217,17 @@ nsDocAccessible::InvalidateCacheSubtree(
     new nsAccReorderEvent(containerAccessible, isAsynch,
                           isUnconditionalEvent,
                           aChild ? childNode.get() : nsnull);
   NS_ENSURE_TRUE(reorderEvent,);
 
   FireDelayedAccessibleEvent(reorderEvent);
 }
 
+// nsIAccessibleDocument method
 NS_IMETHODIMP
 nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode,
                                             PRBool aCanCreate,
                                             nsIAccessible **aAccessible)
 {
   // Find accessible in parent chain of DOM nodes, or return null
   *aAccessible = nsnull;
   nsCOMPtr<nsIDOMNode> currentNode(aNode), parentNode;
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -82,17 +82,16 @@ public:
   nsDocAccessible(nsIDOMNode *aNode, nsIWeakReference* aShell);
   virtual ~nsDocAccessible();
 
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& aName);
   NS_IMETHOD GetDescription(nsAString& aDescription);
   NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
   NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
-  NS_IMETHOD GetParent(nsIAccessible **aParent);
   NS_IMETHOD TakeFocus(void);
 
   // nsIScrollPositionListener
   NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView,
                                       nscoord aX, nscoord aY);
   virtual void ViewPositionDidChange(nsIScrollableView* aScrollable,
                                      nsTArray<nsIWidget::Configuration>* aConfigurations) {}
   NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView,
@@ -106,17 +105,19 @@ public:
   virtual nsresult Shutdown();
   virtual nsIFrame* GetFrame();
   virtual PRBool IsDefunct();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
+
   virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
+  virtual nsIAccessible* GetParent();
 
   // nsIAccessibleText
   NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
 
   // nsDocAccessible
 
   /**
    * Non-virtual method to fire a delayed event after a 0 length timeout.
--- a/accessible/src/base/nsOuterDocAccessible.cpp
+++ b/accessible/src/base/nsOuterDocAccessible.cpp
@@ -94,63 +94,46 @@ nsOuterDocAccessible::GetChildAtPoint(PR
 
   if (aDeepestChild)
     return childAcc->GetDeepestChildAtPoint(aX, aY, aChild);
 
   NS_ADDREF(*aChild = childAcc);
   return NS_OK;
 }
 
-void nsOuterDocAccessible::CacheChildren()
-{  
-  // An outer doc accessible usually has 1 nsDocAccessible child,
-  // but could have none if we can't get to the inner documnet
-  if (!mWeakShell) {
-    mAccChildCount = eChildCountUninitialized;
-    return;   // This outer doc node has been shut down
-  }
-  if (mAccChildCount != eChildCountUninitialized) {
-    return;
-  }
-
-  InvalidateChildren();
-  mAccChildCount = 0;
-
-  // In these variable names, "outer" relates to the nsOuterDocAccessible
-  // as opposed to the nsDocAccessibleWrap which is "inner".
-  // The outer node is a something like a <browser>, <frame>, <iframe>, <page> or
-  // <editor> tag, whereas the inner node corresponds to the inner document root.
+void
+nsOuterDocAccessible::CacheChildren()
+{
+  // An outer doc accessible usually has 1 nsDocAccessible child, but could have
+  // none if we can't get to the inner documnet.
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   NS_ASSERTION(content, "No nsIContent for <browser>/<iframe>/<editor> dom node");
 
   nsCOMPtr<nsIDocument> outerDoc = content->GetDocument();
   if (!outerDoc) {
     return;
   }
 
   nsIDocument *innerDoc = outerDoc->GetSubDocumentFor(content);
   nsCOMPtr<nsIDOMNode> innerNode(do_QueryInterface(innerDoc));
   if (!innerNode) {
     return;
   }
 
   nsCOMPtr<nsIAccessible> innerAccessible;
-  nsCOMPtr<nsIAccessibilityService> accService = 
-    do_GetService("@mozilla.org/accessibilityService;1");
+  nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
   accService->GetAccessibleFor(innerNode, getter_AddRefs(innerAccessible));
   nsRefPtr<nsAccessible> innerAcc(nsAccUtils::QueryAccessible(innerAccessible));
   if (!innerAcc)
     return;
 
   // Success getting inner document as first child -- now we cache it.
-  mAccChildCount = 1;
-  SetFirstChild(innerAccessible); // weak ref
+  mChildren.AppendObject(innerAccessible);
   innerAcc->SetParent(this);
-  innerAcc->SetNextSibling(nsnull);
 }
 
 nsresult
 nsOuterDocAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   nsAutoString tag;
   aAttributes->GetStringProperty(NS_LITERAL_CSTRING("tag"), tag);
   if (!tag.IsEmpty()) {
--- a/accessible/src/base/nsOuterDocAccessible.h
+++ b/accessible/src/base/nsOuterDocAccessible.h
@@ -37,18 +37,24 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsOuterDocAccessible_H_
 #define _nsOuterDocAccessible_H_
 
 #include "nsAccessibleWrap.h"
 #include "nsIAccessible.h"
 
-class nsIWeakReference;
-
+/**
+ * Used for <browser>, <frame>, <iframe>, <page> or editor> elements.
+ * 
+ * In these variable names, "outer" relates to the nsOuterDocAccessible as
+ * opposed to the nsDocAccessibleWrap which is "inner". The outer node is
+ * a something like tags listed above, whereas the inner node corresponds to
+ * the inner document root.
+ */
 class nsOuterDocAccessible : public nsAccessibleWrap
 {
   // XXX: why is it private?
   // CVS comment: <aaronl@netscape.com> 2003-04-01 14:15 Fixing bustage
   NS_DECL_ISUPPORTS_INHERITED
 
 public:
   nsOuterDocAccessible(nsIDOMNode* aNode, 
@@ -65,12 +71,12 @@ public:
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                    PRBool aDeepestChild,
                                    nsIAccessible **aChild);
 
 protected:
   // nsAccessible
-  void CacheChildren();
+  virtual void CacheChildren();
 };
 
 #endif  
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -79,43 +79,46 @@
 #include "nsFocusManager.h"
 
 #ifdef MOZ_XUL
 #include "nsXULTreeAccessible.h"
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
 
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
 // Expanded version of NS_IMPL_ISUPPORTS_INHERITED2 
 // so we can QI directly to concrete nsRootAccessible
 NS_IMPL_QUERY_HEAD(nsRootAccessible)
 NS_IMPL_QUERY_BODY(nsIDOMEventListener)
 if (aIID.Equals(NS_GET_IID(nsRootAccessible)))
   foundInterface = reinterpret_cast<nsISupports*>(this);
 else
 NS_IMPL_QUERY_TAIL_INHERITING(nsDocAccessible)
 
 NS_IMPL_ADDREF_INHERITED(nsRootAccessible, nsDocAccessible) 
 NS_IMPL_RELEASE_INHERITED(nsRootAccessible, nsDocAccessible)
 
-//-----------------------------------------------------
-// construction 
-//-----------------------------------------------------
+////////////////////////////////////////////////////////////////////////////////
+// Constructor/desctructor
+
 nsRootAccessible::nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
   nsDocAccessibleWrap(aDOMNode, aShell)
 {
 }
 
-//-----------------------------------------------------
-// destruction
-//-----------------------------------------------------
 nsRootAccessible::~nsRootAccessible()
 {
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessible
+
 /* readonly attribute AString name; */
 NS_IMETHODIMP
 nsRootAccessible::GetName(nsAString& aName)
 {
   aName.Truncate();
 
   if (!mDocument) {
     return NS_ERROR_FAILURE;
@@ -127,31 +130,16 @@ nsRootAccessible::GetName(nsAString& aNa
       return NS_OK;
     }
   }
 
   nsCOMPtr<nsIDOMNSDocument> document(do_QueryInterface(mDocument));
   return document->GetTitle(aName);
 }
 
-/* readonly attribute nsIAccessible accParent; */
-NS_IMETHODIMP nsRootAccessible::GetParent(nsIAccessible * *aParent) 
-{
-  NS_ENSURE_ARG_POINTER(aParent);
-  *aParent = nsnull;
-
-  if (!mParent) {
-    nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
-    mParent = root;
-  }
-
-  NS_IF_ADDREF(*aParent = mParent);
-  return NS_OK;
-}
-
 /* readonly attribute unsigned long accRole; */
 nsresult
 nsRootAccessible::GetRoleInternal(PRUint32 *aRole) 
 { 
   if (!mDocument) {
     return NS_ERROR_FAILURE;
   }
 
@@ -167,16 +155,17 @@ nsRootAccessible::GetRoleInternal(PRUint
         return NS_OK;
       }
     }
   }
 
   return nsDocAccessibleWrap::GetRoleInternal(aRole);
 }
 
+// nsRootAccessible protected member
 #ifdef MOZ_XUL
 PRUint32 nsRootAccessible::GetChromeFlags()
 {
   // Return the flag set for the top level window as defined 
   // by nsIWebBrowserChrome::CHROME_WINDOW_[FLAGNAME]
   // Not simple: nsIXULWindow is not just a QI from nsIDOMWindow
   nsCOMPtr<nsIDocShellTreeItem> treeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
@@ -576,30 +565,33 @@ void nsRootAccessible::FireCurrentFocusE
         if (targetNode) {
           HandleEventWithTarget(event, targetNode);
         }
       }
     }
   }
 }
 
-// --------------- nsIDOMEventListener Methods (3) ------------------------
+////////////////////////////////////////////////////////////////////////////////
+// nsIDOMEventListener
 
 NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
 {
   // Turn DOM events in accessibility events
   // Get info about event and target
   nsCOMPtr<nsIDOMNode> targetNode;
   GetTargetNode(aEvent, getter_AddRefs(targetNode));
   if (!targetNode)
     return NS_ERROR_FAILURE;
   
   return HandleEventWithTarget(aEvent, targetNode);
 }
 
+
+// nsRootAccessible protected member
 nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
                                                  nsIDOMNode* aTargetNode)
 {
   nsAutoString eventType;
   aEvent->GetType(eventType);
   nsAutoString localName;
   aTargetNode->GetLocalName(localName);
 #ifdef MOZ_XUL
@@ -941,16 +933,19 @@ void nsRootAccessible::GetTargetNode(nsI
 
 void nsRootAccessible::FireFocusCallback(nsITimer *aTimer, void *aClosure)
 {
   nsRootAccessible *rootAccessible = static_cast<nsRootAccessible*>(aClosure);
   NS_ASSERTION(rootAccessible, "How did we get here without a root accessible?");
   rootAccessible->FireCurrentFocusEvent();
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessNode
+
 nsresult
 nsRootAccessible::Init()
 {
   nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
   NS_ENSURE_STATE(root);
 
   root->AddRootAccessible(this);
 
@@ -975,16 +970,17 @@ nsRootAccessible::Shutdown()
   if (mFireFocusTimer) {
     mFireFocusTimer->Cancel();
     mFireFocusTimer = nsnull;
   }
 
   return nsDocAccessibleWrap::Shutdown();
 }
 
+// nsRootAccessible protected member
 already_AddRefed<nsIDocShellTreeItem>
 nsRootAccessible::GetContentDocShell(nsIDocShellTreeItem *aStart)
 {
   if (!aStart) {
     return nsnull;
   }
 
   PRInt32 itemType;
@@ -1031,16 +1027,17 @@ nsRootAccessible::GetContentDocShell(nsI
         NS_ADDREF(aStart = contentTreeItem);
         return aStart;
       }
     }
   }
   return nsnull;
 }
 
+// nsIAccessible method
 NS_IMETHODIMP
 nsRootAccessible::GetRelationByType(PRUint32 aRelationType,
                                     nsIAccessibleRelation **aRelation)
 {
   NS_ENSURE_ARG_POINTER(aRelation);
   *aRelation = nsnull;
 
   if (!mDOMNode || aRelationType != nsIAccessibleRelation::RELATION_EMBEDS) {
@@ -1057,16 +1054,30 @@ nsRootAccessible::GetRelationByType(PRUi
 
     nsCOMPtr<nsIAccessible> acc(do_QueryInterface(accDoc));
     return nsRelUtils::AddTarget(aRelationType, aRelation, acc);
   }
 
   return NS_OK;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessible
+
+nsIAccessible*
+nsRootAccessible::GetParent()
+{
+  // Parent has been setted in nsApplicationAccesible::AddRootAccessible()
+  // when root accessible was intialized.
+  return mParent;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsDocAccessible
+
 void
 nsRootAccessible::FireDocLoadEvents(PRUint32 aEventType)
 {
   if (IsDefunct())
     return;
 
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
@@ -1079,16 +1090,19 @@ nsRootAccessible::FireDocLoadEvents(PRUi
   if (contentType == nsIDocShellTreeItem::typeContent)
     nsDocAccessibleWrap::FireDocLoadEvents(aEventType); // Content might need to fire event
 
   // Root chrome: don't fire event
   mIsContentLoaded = (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
                       aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Protected members
+
 nsresult
 nsRootAccessible::HandlePopupShownEvent(nsIAccessible *aAccessible)
 {
   PRUint32 role = nsAccUtils::Role(aAccessible);
 
   if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
     // Don't fire menupopup events for combobox and autocomplete lists.
     return nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -69,30 +69,30 @@ class nsRootAccessible : public nsDocAcc
   NS_DECL_ISUPPORTS_INHERITED
 
 public:
   nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell);
   virtual ~nsRootAccessible();
 
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& aName);
-  NS_IMETHOD GetParent(nsIAccessible * *aParent);
   NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
                                nsIAccessibleRelation **aRelation);
 
   // nsIDOMEventListener
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
 
   // nsAccessNode
   virtual nsresult Init();
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+  virtual nsIAccessible* GetParent();
 
   // nsDocAccessible
   virtual void FireDocLoadEvents(PRUint32 aEventType);
 
   // nsRootAccessible
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ROOTACCESSIBLE_IMPL_CID)
 
     /**
--- a/accessible/src/base/nsTextAccessible.cpp
+++ b/accessible/src/base/nsTextAccessible.cpp
@@ -65,10 +65,9 @@ nsTextAccessible::AppendTextTo(nsAString
 
   return frame->GetRenderedText(&aText, nsnull, nsnull, aStartOffset, aLength);
 }
 
 void
 nsTextAccessible::CacheChildren()
 {
   // No children for text accessible.
-  mAccChildCount = IsDefunct() ? eChildCountUninitialized : 0;
 }
--- a/accessible/src/html/nsHTMLAreaAccessible.cpp
+++ b/accessible/src/html/nsHTMLAreaAccessible.cpp
@@ -150,10 +150,9 @@ nsHTMLAreaAccessible::GetChildAtPoint(PR
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible protected implementation
 
 void
 nsHTMLAreaAccessible::CacheChildren()
 {
   // No children for aria accessible.
-  mAccChildCount = IsDefunct() ? eChildCountUninitialized : 0;
 }
--- a/accessible/src/html/nsHTMLImageAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageAccessible.cpp
@@ -150,52 +150,38 @@ nsHTMLImageAccessible::GetNameInternal(n
 nsresult
 nsHTMLImageAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   *aRole = mMapElement ? nsIAccessibleRole::ROLE_IMAGE_MAP :
                          nsIAccessibleRole::ROLE_GRAPHIC;
   return NS_OK;
 }
 
-void nsHTMLImageAccessible::CacheChildren()
+void 
+nsHTMLImageAccessible::CacheChildren()
 {
-  if (!mWeakShell) {
-    // This node has been shut down
-    mAccChildCount = eChildCountUninitialized;
-    return;
-  }
-
-  if (mAccChildCount != eChildCountUninitialized) {
-    return;
-  }
-
-  mAccChildCount = 0;
   nsCOMPtr<nsIDOMHTMLCollection> mapAreas = GetAreaCollection();
   if (!mapAreas)
     return;
 
-  PRUint32 numMapAreas;
-  mapAreas->GetLength(&numMapAreas);
-  PRInt32 childCount = 0;
-  
+  PRUint32 areaCount = 0;
+  mapAreas->GetLength(&areaCount);
+
   nsCOMPtr<nsIAccessible> areaAccessible;
-  nsRefPtr<nsAccessible> prevAcc;
-  while (childCount < (PRInt32)numMapAreas && 
-         (areaAccessible = GetAreaAccessible(mapAreas, childCount)) != nsnull) {
-    if (prevAcc)
-      prevAcc->SetNextSibling(areaAccessible);
-    else
-      SetFirstChild(areaAccessible);
+  nsRefPtr<nsAccessible> areaAcc;
 
-    ++ childCount;
+  for (PRUint32 areaIdx = 0; areaIdx < areaCount; areaIdx++) {
+    areaAccessible = GetAreaAccessible(mapAreas, areaIdx);
+    if (!areaAccessible)
+      return;
 
-    prevAcc = nsAccUtils::QueryAccessible(areaAccessible);
-    prevAcc->SetParent(this);
+    mChildren.AppendObject(areaAccessible);
+    areaAcc = nsAccUtils::QueryObject<nsAccessible>(areaAccessible);
+    areaAcc->SetParent(this);
   }
-  mAccChildCount = childCount;
 }
 
 NS_IMETHODIMP
 nsHTMLImageAccessible::GetNumActions(PRUint8 *aNumActions)
 {
   NS_ENSURE_ARG_POINTER(aNumActions);
   *aNumActions = 0;
 
--- a/accessible/src/html/nsHTMLImageAccessible.h
+++ b/accessible/src/html/nsHTMLImageAccessible.h
@@ -78,16 +78,17 @@ public:
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 
 protected:
   // nsAccessible
   virtual void CacheChildren();
 
+  // nsHTMLImageAccessible
   already_AddRefed<nsIDOMHTMLCollection> GetAreaCollection();
   already_AddRefed<nsIAccessible>
     GetAreaAccessible(nsIDOMHTMLCollection* aAreaNodes, PRInt32 aAreaNum);
 
   // Reference on linked map element if any.
   nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
 
   // Cache of area accessibles. We do not use common cache because images can
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -300,38 +300,42 @@ NS_IMETHODIMP nsHTMLSelectableAccessible
   }
   return NS_OK;
 }
 
 /** ------------------------------------------------------ */
 /**  First, the common widgets                             */
 /** ------------------------------------------------------ */
 
-/** ----- nsHTMLSelectListAccessible ----- */
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLSelectListAccessible
+////////////////////////////////////////////////////////////////////////////////
 
 /** Default Constructor */
 nsHTMLSelectListAccessible::nsHTMLSelectListAccessible(nsIDOMNode* aDOMNode, 
                                                        nsIWeakReference* aShell)
 :nsHTMLSelectableAccessible(aDOMNode, aShell)
 {
 }
 
-/**
-  * As a nsHTMLSelectListAccessible we can have the following states:
-  *     nsIAccessibleStates::STATE_MULTISELECTABLE
-  *     nsIAccessibleStates::STATE_EXTSELECTABLE
-  */
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLSelectListAccessible: nsAccessible public
+
 nsresult
 nsHTMLSelectListAccessible::GetStateInternal(PRUint32 *aState,
                                              PRUint32 *aExtraState)
 {
   nsresult rv = nsHTMLSelectableAccessible::GetStateInternal(aState,
                                                              aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
 
+  // As a nsHTMLSelectListAccessible we can have the following states:
+  //   nsIAccessibleStates::STATE_MULTISELECTABLE
+  //   nsIAccessibleStates::STATE_EXTSELECTABLE
+
   nsCOMPtr<nsIDOMHTMLSelectElement> select (do_QueryInterface(mDOMNode));
   if (select) {
     if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
       // Treat first focusable option node as actual focus, in order
       // to avoid confusing JAWS, which needs focus on the option
       nsCOMPtr<nsIDOMNode> focusedOption;
       nsHTMLSelectOptionAccessible::GetFocusedOptionNode(mDOMNode, 
                                                          getter_AddRefs(focusedOption));
@@ -355,119 +359,73 @@ nsHTMLSelectListAccessible::GetRoleInter
   if (nsAccUtils::Role(mParent) == nsIAccessibleRole::ROLE_COMBOBOX)
     *aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST;
   else
     *aRole = nsIAccessibleRole::ROLE_LISTBOX;
 
   return NS_OK;
 }
 
-already_AddRefed<nsIAccessible>
-nsHTMLSelectListAccessible::AccessibleForOption(nsIAccessibilityService *aAccService,
-                                                nsIContent *aContent,
-                                                nsIAccessible *aLastGoodAccessible,
-                                                PRInt32 *aChildCount)
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLSelectListAccessible: nsAccessible protected
+
+void
+nsHTMLSelectListAccessible::CacheChildren()
 {
-  nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(aContent));
-  NS_ASSERTION(domNode, "DOM node is null");
-  // Accessibility service will initialize & cache any accessibles created
-  nsCOMPtr<nsIAccessible> accessible;
-  aAccService->GetAccessibleInWeakShell(domNode, mWeakShell, getter_AddRefs(accessible));
-  nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(accessible));
-  if (!acc)
-    return nsnull;
-
-  ++ *aChildCount;
-  acc->SetParent(this);
-  nsRefPtr<nsAccessible> prevAcc =
-    nsAccUtils::QueryAccessible(aLastGoodAccessible);
-  if (prevAcc)
-    prevAcc->SetNextSibling(accessible);
-
-  if (!mFirstChild)
-    mFirstChild = accessible;
-
-  return accessible.forget();
+  // Cache accessibles for <optgroup> and <option> DOM decendents as children,
+  // as well as the accessibles for them. Avoid whitespace text nodes. We want
+  // to count all the <optgroup>s and <option>s as children because we want
+  // a flat tree under the Select List.
+  
+  nsCOMPtr<nsIContent> selectContent(do_QueryInterface(mDOMNode));
+  CacheOptSiblings(selectContent);
 }
 
-already_AddRefed<nsIAccessible>
-nsHTMLSelectListAccessible::CacheOptSiblings(nsIAccessibilityService *aAccService,
-                                             nsIContent *aParentContent,
-                                             nsIAccessible *aLastGoodAccessible,
-                                             PRInt32 *aChildCount)
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLSelectListAccessible protected
+
+void
+nsHTMLSelectListAccessible::CacheOptSiblings(nsIContent *aParentContent)
 {
-  // Recursive helper for CacheChildren()
-
   PRUint32 numChildren = aParentContent->GetChildCount();
-  nsCOMPtr<nsIAccessible> lastGoodAccessible(aLastGoodAccessible);
-  nsCOMPtr<nsIAccessible> newAccessible;
-
   for (PRUint32 count = 0; count < numChildren; count ++) {
     nsIContent *childContent = aParentContent->GetChildAt(count);
     if (!childContent->IsHTML()) {
       continue;
     }
+
     nsCOMPtr<nsIAtom> tag = childContent->Tag();
-    if (tag == nsAccessibilityAtoms::option || tag == nsAccessibilityAtoms::optgroup) {
-      newAccessible = AccessibleForOption(aAccService,
-                                           childContent,
-                                           lastGoodAccessible,
-                                           aChildCount);
-      if (newAccessible) {
-        lastGoodAccessible = newAccessible;
+    if (tag == nsAccessibilityAtoms::option ||
+        tag == nsAccessibilityAtoms::optgroup) {
+
+      // Get an accessible for option or optgroup and cache it.
+      nsCOMPtr<nsIDOMNode> childNode(do_QueryInterface(childContent));
+
+      nsCOMPtr<nsIAccessible> accessible;
+      GetAccService()->GetAccessibleInWeakShell(childNode, mWeakShell,
+                                                getter_AddRefs(accessible));
+      if (accessible) {
+        mChildren.AppendObject(accessible);
+
+        nsRefPtr<nsAccessible> acc =
+          nsAccUtils::QueryObject<nsAccessible>(accessible);
+        acc->SetParent(this);
       }
-      if (tag == nsAccessibilityAtoms::optgroup) {
-        newAccessible = CacheOptSiblings(aAccService, childContent,
-                                         lastGoodAccessible, aChildCount);
-        if (newAccessible) {
-          lastGoodAccessible = newAccessible;
-        }
-      }
+
+      // Deep down into optgroup element.
+      if (tag == nsAccessibilityAtoms::optgroup)
+        CacheOptSiblings(childContent);
     }
   }
-
-  if (lastGoodAccessible) {
-    nsRefPtr<nsAccessible> lastAcc =
-      nsAccUtils::QueryAccessible(lastGoodAccessible);
-    lastAcc->SetNextSibling(nsnull);
-  }
-
-  return lastGoodAccessible.forget();
 }
 
-/**
-  * Cache the children and child count of a Select List Accessible. We want to count 
-  *  all the <optgroup>s and <option>s as children because we want a 
-  *  flat tree under the Select List.
-  */
 
-void nsHTMLSelectListAccessible::CacheChildren()
-{
-  // Cache the number of <optgroup> and <option> DOM decendents,
-  // as well as the accessibles for them. Avoid whitespace text nodes.
-
-  nsCOMPtr<nsIContent> selectContent(do_QueryInterface(mDOMNode));
-  nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
-  if (!selectContent || !accService) {
-    mAccChildCount = eChildCountUninitialized;
-    return;
-  }
-
-  if (mAccChildCount != eChildCountUninitialized) {
-    return;
-  }
-
-  mAccChildCount = 0; // Avoid reentry
-  PRInt32 childCount = 0;
-  nsCOMPtr<nsIAccessible> lastGoodAccessible =
-    CacheOptSiblings(accService, selectContent, nsnull, &childCount);
-  mAccChildCount = childCount;
-}
-
-/** ----- nsHTMLSelectOptionAccessible ----- */
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLSelectOptionAccessible
+////////////////////////////////////////////////////////////////////////////////
 
 /** Default Constructor */
 nsHTMLSelectOptionAccessible::nsHTMLSelectOptionAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
 nsHyperTextAccessibleWrap(aDOMNode, aShell)
 {
   nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
   nsCOMPtr<nsIDOMNode> parentNode;
   aDOMNode->GetParentNode(getter_AddRefs(parentNode));
@@ -832,17 +790,17 @@ void nsHTMLSelectOptionAccessible::Selec
       !aPossibleOption->IsHTML()) {
     return;
   }
 
   nsCOMPtr<nsIDOMNode> optionNode(do_QueryInterface(aPossibleOption));
   NS_ASSERTION(optionNode, "No option node for nsIContent with option tag!");
 
   nsCOMPtr<nsIAccessible> multiSelect =
-    nsAccUtils::GetMultiSelectFor(optionNode);
+    nsAccUtils::GetMultiSelectableContainer(optionNode);
   if (!multiSelect)
     return;
 
   nsCOMPtr<nsIAccessible> optionAccessible;
   GetAccService()->GetAccessibleFor(optionNode,
                                     getter_AddRefs(optionAccessible));
   if (!optionAccessible)
     return;
@@ -880,17 +838,19 @@ nsIContent* nsHTMLSelectOptionAccessible
         selAcc->GetState(aState, aExtraState);
         return content;
       }
     }
   }
   return nsnull; 
 }
 
-/** ----- nsHTMLSelectOptGroupAccessible ----- */
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLSelectOptGroupAccessible
+////////////////////////////////////////////////////////////////////////////////
 
 /** Default Constructor */
 nsHTMLSelectOptGroupAccessible::nsHTMLSelectOptGroupAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
 nsHTMLSelectOptionAccessible(aDOMNode, aShell)
 {
 }
 
 nsresult
@@ -924,93 +884,76 @@ NS_IMETHODIMP nsHTMLSelectOptGroupAccess
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP nsHTMLSelectOptGroupAccessible::GetNumActions(PRUint8 *_retval)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-void nsHTMLSelectOptGroupAccessible::CacheChildren()
-{
-  if (!mWeakShell) {
-    // This node has been shut down
-    mAccChildCount = eChildCountUninitialized;
-    return;
-  }
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLSelectOptGroupAccessible: nsAccessible protected
 
-  if (mAccChildCount == eChildCountUninitialized) {
-    // XXX To do (bug 378612) - create text child for the anonymous attribute content, so that
-    // nsIAccessibleText is supported for the <optgroup> as it is for an <option>
-    // Attribute content is what layout creates for the label="foo" on the <optgroup>
-    // See eStyleContentType_Attr and CreateAttributeContent() in nsCSSFrameConstructor
-    mAccChildCount = 0;
-    SetFirstChild(nsnull);
-  }
+void
+nsHTMLSelectOptGroupAccessible::CacheChildren()
+{
+  // XXX To do (bug 378612) - create text child for the anonymous attribute
+  // content, so that nsIAccessibleText is supported for the <optgroup> as it is
+  // for an <option>. Attribute content is what layout creates for
+  // the label="foo" on the <optgroup>. See eStyleContentType_Attr and
+  // CreateAttributeContent() in nsCSSFrameConstructor
 }
 
 /** ------------------------------------------------------ */
 /**  Finally, the Combobox widgets                         */
 /** ------------------------------------------------------ */
 
-/** ----- nsHTMLComboboxAccessible ----- */
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLComboboxAccessible
+////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLComboboxAccessible::nsHTMLComboboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
 nsAccessibleWrap(aDOMNode, aShell)
 {
 }
 
 /** We are a combobox */
 nsresult
 nsHTMLComboboxAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   *aRole = nsIAccessibleRole::ROLE_COMBOBOX;
   return NS_OK;
 }
 
-void nsHTMLComboboxAccessible::CacheChildren()
+void
+nsHTMLComboboxAccessible::CacheChildren()
 {
-  if (!mWeakShell) {
-    // This node has been shut down
-    mAccChildCount = eChildCountUninitialized;
+  nsIFrame* frame = GetFrame();
+  if (!frame)
+    return;
+
+  nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
+  if (!comboFrame)
     return;
+
+  nsIFrame *listFrame = comboFrame->GetDropDown();
+  if (!listFrame)
+    return;
+
+  if (!mListAccessible) {
+    mListAccessible = 
+      new nsHTMLComboboxListAccessible(mParent, mDOMNode, mWeakShell);
+    if (!mListAccessible)
+      return;
+
+    mListAccessible->Init();
   }
 
-  if (mAccChildCount == eChildCountUninitialized) {
-    mAccChildCount = 0;
-
-    nsIFrame *frame = GetFrame();
-    if (!frame) {
-      return;
-    }
-    nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
-    if (!comboFrame) {
-      return;
-    }
-    nsIFrame *listFrame = comboFrame->GetDropDown();
-    if (!listFrame) {
-      return;
-    }
-
-    if (!mListAccessible) {
-      mListAccessible = 
-        new nsHTMLComboboxListAccessible(mParent, mDOMNode, mWeakShell);
-      if (!mListAccessible)
-        return;
-
-      mListAccessible->Init();
-    }
-
-    SetFirstChild(mListAccessible);
-
-    mListAccessible->SetParent(this);
-    mListAccessible->SetNextSibling(nsnull);
-
-    ++ mAccChildCount;  // List accessible child successfully added
-  }
+  mChildren.AppendObject(mListAccessible);
+  mListAccessible->SetParent(this);
 }
 
 nsresult
 nsHTMLComboboxAccessible::Shutdown()
 {
   nsAccessibleWrap::Shutdown();
 
   if (mListAccessible) {
@@ -1149,16 +1092,17 @@ NS_IMETHODIMP nsHTMLComboboxAccessible::
   if (comboFrame->IsDroppedDown())
     aName.AssignLiteral("close"); 
   else
     aName.AssignLiteral("open"); 
 
   return NS_OK;
 }
 
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLComboboxListAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLComboboxListAccessible::nsHTMLComboboxListAccessible(nsIAccessible *aParent,
                                                            nsIDOMNode* aDOMNode,
                                                            nsIWeakReference* aShell):
 nsHTMLSelectListAccessible(aDOMNode, aShell)
@@ -1200,43 +1144,35 @@ nsHTMLComboboxListAccessible::GetStateIn
   if (comboFrame && comboFrame->IsDroppedDown())
     *aState |= nsIAccessibleStates::STATE_FLOATING;
   else
     *aState |= nsIAccessibleStates::STATE_INVISIBLE;
 
   return NS_OK;
 }
 
-/** Return our cached parent */
-NS_IMETHODIMP nsHTMLComboboxListAccessible::GetParent(nsIAccessible **aParent)
-{
-  NS_IF_ADDREF(*aParent = mParent);
-  return NS_OK;
-}
-
 NS_IMETHODIMP nsHTMLComboboxListAccessible::GetUniqueID(void **aUniqueID)
 {
   // Since mDOMNode is same for all tree item, use |this| pointer as the unique Id
   *aUniqueID = static_cast<void*>(this);
   return NS_OK;
 }
 
 /**
   * Gets the bounds for the areaFrame.
   *     Walks the Frame tree and checks for proper frames.
   */
 void nsHTMLComboboxListAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame)
 {
   *aBoundingFrame = nsnull;
 
-  nsCOMPtr<nsIAccessible> comboAccessible;
-  GetParent(getter_AddRefs(comboAccessible));
-  if (!comboAccessible) {
+  nsCOMPtr<nsIAccessible> comboAccessible = GetParent();
+  if (!comboAccessible)
     return;
-  }
+
   if (0 == (nsAccUtils::State(comboAccessible) & nsIAccessibleStates::STATE_COLLAPSED)) {
     nsHTMLSelectListAccessible::GetBoundsRect(aBounds, aBoundingFrame);
     return;
   }
    // get our first option
   nsCOMPtr<nsIDOMNode> child;
   mDOMNode->GetFirstChild(getter_AddRefs(child));
 
@@ -1254,8 +1190,15 @@ void nsHTMLComboboxListAccessible::GetBo
   if (!frame) {
     *aBoundingFrame = nsnull;
     return;
   }
 
   *aBoundingFrame = frame->GetParent();
   aBounds = (*aBoundingFrame)->GetRect();
 }
+
+// nsHTMLComboboxListAccessible. nsAccessible public mehtod
+nsIAccessible*
+nsHTMLComboboxListAccessible::GetParent()
+{
+  return mParent;
+}
--- a/accessible/src/html/nsHTMLSelectAccessible.h
+++ b/accessible/src/html/nsHTMLSelectAccessible.h
@@ -125,28 +125,26 @@ public:
   nsHTMLSelectListAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
   virtual ~nsHTMLSelectListAccessible() {}
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
 protected:
-  void CacheChildren();
+
+  // nsAccessible
+  virtual void CacheChildren();
 
-  already_AddRefed<nsIAccessible>
-    AccessibleForOption(nsIAccessibilityService *aAccService,
-                        nsIContent *aContent,
-                        nsIAccessible *aLastGoodAccessible,
-                        PRInt32 *aChildCount);
-  already_AddRefed<nsIAccessible>
-    CacheOptSiblings(nsIAccessibilityService *aAccService,
-                     nsIContent *aParentContent,
-                     nsIAccessible *aLastGoodAccessible,
-                     PRInt32 *aChildCount);
+  // nsHTMLSelectListAccessible
+
+  /**
+   * Recursive helper for CacheChildren().
+   */
+  void CacheOptSiblings(nsIContent *aParentContent);
 };
 
 /*
  * Options inside the select, contained within the list
  */
 class nsHTMLSelectOptionAccessible : public nsHyperTextAccessibleWrap
 {
 public:
@@ -196,17 +194,18 @@ public:
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
 protected:
-  void CacheChildren();
+  // nsAccessible
+  virtual void CacheChildren();
 };
 
 /** ------------------------------------------------------ */
 /**  Finally, the Combobox widgets                         */
 /** ------------------------------------------------------ */
 
 class nsHTMLComboboxListAccessible;
 
@@ -231,18 +230,20 @@ public:
   // nsAccessNode
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
 protected:
-  void CacheChildren();
+  // nsAccessible
+  virtual void CacheChildren();
 
+  // nsHTMLComboboxAccessible
   already_AddRefed<nsIAccessible> GetFocusedOptionAccessible();
 
 private:
   nsRefPtr<nsHTMLComboboxListAccessible> mListAccessible;
 };
 
 /*
  * A class that represents the window that lives to the right
@@ -254,20 +255,20 @@ class nsHTMLComboboxListAccessible : pub
 public:
 
   nsHTMLComboboxListAccessible(nsIAccessible *aParent, 
                                nsIDOMNode* aDOMNode, 
                                nsIWeakReference* aShell);
   virtual ~nsHTMLComboboxListAccessible() {}
 
   // nsIAccessible
-  NS_IMETHOD GetParent(nsIAccessible **aParent);
   NS_IMETHOD GetUniqueID(void **aUniqueID);
 
   // nsAccessNode
   virtual nsIFrame* GetFrame();
 
   // nsAccessible
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
+  virtual nsIAccessible* GetParent();
 };
 
 #endif
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -427,16 +427,20 @@ nsHTMLTableHeaderCellAccessible::GetRole
         *aRole = nsIAccessibleRole::ROLE_COLUMNHEADER;
       else
         *aRole = nsIAccessibleRole::ROLE_ROWHEADER;
       
       return NS_OK;
     }
   }
 
+  // No elements in siblings what means the table has one column only. Therefore
+  // it should be column header.
+  *aRole = nsIAccessibleRole::ROLE_COLUMNHEADER;
+
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLTableAccessible::
@@ -450,57 +454,37 @@ nsHTMLTableAccessible::
 
 NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible,
                              nsHTMLTableAccessible, nsIAccessibleTable)
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsAccessible implementation
 
-void nsHTMLTableAccessible::CacheChildren()
+void
+nsHTMLTableAccessible::CacheChildren()
 {
-  if (!mWeakShell) {
-    // This node has been shut down
-    mAccChildCount = eChildCountUninitialized;
-    return;
-  }
-  
-  if (mAccChildCount == eChildCountUninitialized) {
-    nsAccessible::CacheChildren();
-    nsCOMPtr<nsIAccessible> captionAccessible;
-    while (NextChild(captionAccessible)) {
-      if (nsAccUtils::Role(captionAccessible) == nsIAccessibleRole::ROLE_CAPTION) {
-        nsCOMPtr<nsIAccessible> captionParentAccessible;
-        captionAccessible->GetParent(getter_AddRefs(captionParentAccessible));
-        if (captionParentAccessible != this) {
-          NS_WARNING("Should not happen: parser ensures caption is the table's child, not the tbody's");
-          return;
-        }
-        nsCOMPtr<nsIAccessible> beforeCaptionAccessible;
-        captionAccessible->GetPreviousSibling(getter_AddRefs(beforeCaptionAccessible));
-        if (beforeCaptionAccessible) {
-          // Move caption accessible so that it's the first child
-          nsRefPtr<nsAccessible> acc =
-            nsAccUtils::QueryAccessible(beforeCaptionAccessible);
+  nsAccessible::CacheChildren();
+
+  // Move caption accessible so that it's the first child.
+  PRInt32 length = mChildren.Count();
+  for (PRInt32 idx = 0; idx < length; idx++) {
+    // Check for the first caption, because nsAccessibilityService ensures we
+    // don't create accessibles for the other captions, since only the first is
+    // actually visible.
 
-          nsCOMPtr<nsIAccessible> afterCaptionAccessible;
-          captionAccessible->GetNextSibling(getter_AddRefs(afterCaptionAccessible));
-          acc->SetNextSibling(afterCaptionAccessible);
-
-          GetFirstChild(getter_AddRefs(afterCaptionAccessible));
-          SetFirstChild(captionAccessible);
+    nsIAccessible* child = mChildren.ObjectAt(idx);
+    if (nsAccUtils::Role(child) == nsIAccessibleRole::ROLE_CAPTION) {
+      if (idx == 0)
+        break;
 
-          acc = nsAccUtils::QueryAccessible(captionAccessible);
-          acc->SetNextSibling(afterCaptionAccessible);        
-        }
-        // Don't check for more captions, because nsAccessibilityService ensures
-        // we don't create accessibles for the other captions, since only the
-        // first is actually visible
-        break;
-      }
+      nsCOMPtr<nsIAccessible> tmp = mChildren.ObjectAt(0);
+      mChildren.ReplaceObjectAt(child, 0);
+      mChildren.ReplaceObjectAt(tmp, idx);
+      break;
     }
   }
 }
 
 nsresult
 nsHTMLTableAccessible::GetRoleInternal(PRUint32 *aResult)
 {
   *aResult = nsIAccessibleRole::ROLE_TABLE;
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -258,30 +258,29 @@ NS_IMETHODIMP nsHTMLLIAccessible::GetBou
   rv = mBulletAccessible->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *x = bulletX; // Move x coordinate of list item over to cover bullet as well
   *width += bulletWidth;
   return NS_OK;
 }
 
-void nsHTMLLIAccessible::CacheChildren()
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLLIAccessible: nsAccessible protected
+
+void
+nsHTMLLIAccessible::CacheChildren()
 {
-  if (!mWeakShell || mAccChildCount != eChildCountUninitialized) {
-    return;
+  if (mBulletAccessible) {
+    mChildren.AppendObject(mBulletAccessible);
+    mBulletAccessible->SetParent(this);
   }
 
+  // Cache children from subtree.
   nsAccessibleWrap::CacheChildren();
-
-  if (mBulletAccessible) {
-    mBulletAccessible->SetNextSibling(mFirstChild);
-    mBulletAccessible->SetParent(this);
-    SetFirstChild(mBulletAccessible);
-    ++ mAccChildCount;
-  }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLListBulletAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLListBulletAccessible::
   nsHTMLListBulletAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell,
@@ -327,37 +326,34 @@ nsHTMLListBulletAccessible::GetStateInte
   nsresult rv = nsLeafAccessible::GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
 
   *aState &= ~nsIAccessibleStates::STATE_FOCUSABLE;
   *aState |= nsIAccessibleStates::STATE_READONLY;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHTMLListBulletAccessible::GetParent(nsIAccessible **aParent)
-{
-  NS_ENSURE_ARG_POINTER(aParent);
-
-  NS_IF_ADDREF(*aParent = mParent);
-  return NS_OK;
-}
-
 nsresult
 nsHTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
                                          PRUint32 aLength)
 {
   PRUint32 maxLength = mBulletText.Length() - aStartOffset;
   if (aLength > maxLength) {
     aLength = maxLength;
   }
   aText += nsDependentSubstring(mBulletText, aStartOffset, aLength);
   return NS_OK;
 }
 
+nsIAccessible*
+nsHTMLListBulletAccessible::GetParent()
+{
+  return mParent;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLListAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLListAccessible, nsHyperTextAccessible)
 
 nsresult
 nsHTMLListAccessible::GetRoleInternal(PRUint32 *aRole)
--- a/accessible/src/html/nsHTMLTextAccessible.h
+++ b/accessible/src/html/nsHTMLTextAccessible.h
@@ -101,27 +101,28 @@ public:
   nsHTMLListBulletAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell,
                              const nsAString& aBulletText);
 
   // nsIAccessNode
   NS_IMETHOD GetUniqueID(void **aUniqueID);
 
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& aName);
-  NS_IMETHOD GetParent(nsIAccessible **aParent);
 
   // nsAccessNode
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
                                 PRUint32 aLength);
 
+  virtual nsIAccessible* GetParent();
+
 protected:
   // XXX: Ideally we'd get the bullet text directly from the bullet frame via
   // nsBulletFrame::GetListItemText(), but we'd need an interface for getting
   // text from contentless anonymous frames. Perhaps something like
   // nsIAnonymousFrame::GetText() ? However, in practice storing the bullet text
   // here should not be a problem if we invalidate the right parts of
   // the accessibility cache when mutation events occur.
   nsString mBulletText;
@@ -156,14 +157,16 @@ public:
   // nsAccessNode
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
 protected:
-  void CacheChildren();  // Include bullet accessible
+  // nsAccessible
+  virtual void CacheChildren();
 
+private:
   nsRefPtr<nsHTMLListBulletAccessible> mBulletAccessible;
 };
 
 #endif  
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -196,59 +196,54 @@ nsHyperTextAccessible::GetStateInternal(
   GetChildCount(&childCount);
   if (childCount > 0) {
     *aExtraState |= nsIAccessibleStates::EXT_STATE_SELECTABLE_TEXT;
   }
 
   return NS_OK;
 }
 
-void nsHyperTextAccessible::CacheChildren()
+void
+nsHyperTextAccessible::CacheChildren()
 {
-  if (!mWeakShell) {
-    // This node has been shut down
-    mAccChildCount = eChildCountUninitialized;
+  PRUint32 role;
+  GetRoleInternal(&role);
+  if (role != nsIAccessibleRole::ROLE_ENTRY &&
+      role != nsIAccessibleRole::ROLE_PASSWORD_TEXT) {
+    nsAccessible::CacheChildren();
+    return;
+  }
+
+  nsCOMPtr<nsIEditor> editor;
+  GetAssociatedEditor(getter_AddRefs(editor));
+  if (!editor) {
+    nsAccessible::CacheChildren();
     return;
   }
 
-  // Special case for text entry fields, go directly to editor's root for children
-  if (mAccChildCount == eChildCountUninitialized) {
-    PRUint32 role;
-    GetRoleInternal(&role);
-    if (role != nsIAccessibleRole::ROLE_ENTRY && role != nsIAccessibleRole::ROLE_PASSWORD_TEXT) {
-      nsAccessible::CacheChildren();
-      return;
-    }
-    nsCOMPtr<nsIEditor> editor;
-    GetAssociatedEditor(getter_AddRefs(editor));
-    if (!editor) {
-      nsAccessible::CacheChildren();
-      return;
-    }
-    mAccChildCount = 0;  // Avoid reentry
-    nsCOMPtr<nsIDOMElement> editorRoot;
-    editor->GetRootElement(getter_AddRefs(editorRoot));
-    nsCOMPtr<nsIDOMNode> editorRootDOMNode = do_QueryInterface(editorRoot);
-    if (!editorRootDOMNode) {
-      return;
-    }
-    nsAccessibleTreeWalker walker(mWeakShell, editorRootDOMNode, PR_TRUE);
-    nsRefPtr<nsAccessible> prevAcc;
-    PRInt32 childCount = 0;
-    walker.GetFirstChild();
-    SetFirstChild(walker.mState.accessible);
+  // Special case for text entry fields, go directly to editor's root for
+  // children.
+
+  nsCOMPtr<nsIDOMElement> editorRoot;
+  editor->GetRootElement(getter_AddRefs(editorRoot));
+  nsCOMPtr<nsIDOMNode> editorRootDOMNode = do_QueryInterface(editorRoot);
+  if (!editorRootDOMNode)
+    return;
 
-    while (walker.mState.accessible) {
-      ++ childCount;
-      prevAcc = nsAccUtils::QueryAccessible(walker.mState.accessible);
-      prevAcc->SetParent(this);
-      walker.GetNextSibling();
-      prevAcc->SetNextSibling(walker.mState.accessible);
-    }
-    mAccChildCount = childCount;
+  nsAccessibleTreeWalker walker(mWeakShell, editorRootDOMNode, PR_TRUE);
+
+  walker.GetFirstChild();
+  while (walker.mState.accessible) {
+    mChildren.AppendObject(walker.mState.accessible);
+
+    nsRefPtr<nsAccessible> acc =
+      nsAccUtils::QueryObject<nsAccessible>(walker.mState.accessible);
+    acc->SetParent(this);
+
+    walker.GetNextSibling();
   }
 }
 
 // Substring must be entirely within the same text node
 nsIntRect nsHyperTextAccessible::GetBoundsForString(nsIFrame *aFrame, PRUint32 aStartRenderedOffset,
                                                     PRUint32 aEndRenderedOffset)
 {
   nsIntRect screenRect;
@@ -861,20 +856,21 @@ nsHyperTextAccessible::GetRelativeOffset
   NS_ENSURE_SUCCESS(rv, -1);
 
   if (!finalAccessible && aDirection == eDirPrevious) {
     // If we reached the end during search, this means we didn't find the DOM point
     // and we're actually at the start of the paragraph
     hyperTextOffset = 0;
   }  
   else if (aAmount == eSelectBeginLine) {
+    nsIAccessible *firstChild = mChildren.SafeObjectAt(0);
     // For line selection with needsStart, set start of line exactly to line break
-    if (pos.mContentOffset == 0 && mFirstChild && 
-        nsAccUtils::Role(mFirstChild) == nsIAccessibleRole::ROLE_STATICTEXT &&
-        nsAccUtils::TextLength(mFirstChild) == hyperTextOffset) {
+    if (pos.mContentOffset == 0 && firstChild &&
+        nsAccUtils::Role(firstChild) == nsIAccessibleRole::ROLE_STATICTEXT &&
+        nsAccUtils::TextLength(firstChild) == hyperTextOffset) {
       // XXX Bullet hack -- we should remove this once list bullets use anonymous content
       hyperTextOffset = 0;
     }
     if (!aNeedsStart && hyperTextOffset > 0) {
       -- hyperTextOffset;
     }
   }
   else if (aAmount == eSelectEndLine && finalAccessible) { 
--- a/accessible/src/html/nsHyperTextAccessible.h
+++ b/accessible/src/html/nsHyperTextAccessible.h
@@ -81,17 +81,16 @@ public:
   NS_DECL_NSIACCESSIBLEHYPERTEXT
   NS_DECL_NSIACCESSIBLEEDITABLETEXT
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_HYPERTEXTACCESSIBLE_IMPL_CID)
 
   // nsAccessible
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
-  void CacheChildren();
 
   // Convert content offset to rendered text offset  
   static nsresult ContentToRenderedOffset(nsIFrame *aFrame, PRInt32 aContentOffset,
                                           PRUint32 *aRenderedOffset);
   
   // Convert rendered text offset to content offset
   static nsresult RenderedToContentOffset(nsIFrame *aFrame, PRUint32 aRenderedOffset,
                                           PRInt32 *aContentOffset);
@@ -150,16 +149,22 @@ public:
   nsresult HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset,
                                       PRInt32 aEndHTOffset,
                                       nsIDOMNode **aStartNode,
                                       PRInt32 *aStartOffset,
                                       nsIDOMNode **aEndNode,
                                       PRInt32 *aEndOffset);
 
 protected:
+
+  // nsAccessible
+  virtual void CacheChildren();
+
+  // nsHyperTextAccessible
+
   /*
    * This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
    * @param aType, eGetBefore, eGetAt, eGetAfter
    * @param aBoundaryType, char/word-start/word-end/line-start/line-end/paragraph/attribute
    * @param aOffset, offset into the hypertext to start from
    * @param *aStartOffset, the resulting start offset for the returned substring
    * @param *aEndOffset, the resulting end offset for the returned substring
    * @param aText, the resulting substring
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -1100,38 +1100,33 @@ nsAccessibleWrap::Next(ULONG aNumElement
   *aNumElementsFetched = 0;
 
   if (aNumElementsRequested <= 0 || !aPVar)
     return E_INVALIDARG;
 
   if (mEnumVARIANTPosition == kIEnumVariantDisconnected)
     return CO_E_OBJNOTCONNECTED;
 
-  nsCOMPtr<nsIAccessible> traversedAcc;
-  nsresult rv = GetChildAt(mEnumVARIANTPosition, getter_AddRefs(traversedAcc));
-  if (!traversedAcc)
-    return S_FALSE;
-
-  for (PRUint32 i = 0; i < aNumElementsRequested; i++) {
-    VariantInit(&aPVar[i]);
+  PRUint32 numElementsFetched = 0;
+  for (; numElementsFetched < aNumElementsRequested;
+       numElementsFetched++, mEnumVARIANTPosition++) {
 
-    aPVar[i].pdispVal = NativeAccessible(traversedAcc);
-    aPVar[i].vt = VT_DISPATCH;
-    (*aNumElementsFetched)++;
-
-    nsCOMPtr<nsIAccessible> nextAcc;
-    traversedAcc->GetNextSibling(getter_AddRefs(nextAcc));
-    if (!nextAcc)
+    nsIAccessible* accessible = GetChildAt(mEnumVARIANTPosition);
+    if (!accessible)
       break;
 
-    traversedAcc = nextAcc;
+    VariantInit(&aPVar[numElementsFetched]);
+
+    aPVar[numElementsFetched].pdispVal = NativeAccessible(accessible);
+    aPVar[numElementsFetched].vt = VT_DISPATCH;
   }
 
-  mEnumVARIANTPosition += *aNumElementsFetched;
-  return (*aNumElementsFetched) < aNumElementsRequested ? S_FALSE : S_OK;
+  (*aNumElementsFetched) = numElementsFetched;
+
+  return numElementsFetched < aNumElementsRequested ? S_FALSE : S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::Skip(ULONG aNumElements)
 {
--- a/accessible/src/msaa/nsHTMLWin32ObjectAccessible.cpp
+++ b/accessible/src/msaa/nsHTMLWin32ObjectAccessible.cpp
@@ -44,74 +44,33 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLWin32ObjectOwnerAccessible::
   nsHTMLWin32ObjectOwnerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell,
                                    void* aHwnd) :
   nsAccessibleWrap(aNode, aShell)
 {
   mHwnd = aHwnd;
+
+  // Our only child is a nsHTMLWin32ObjectAccessible object.
+  mNativeAccessible = new nsHTMLWin32ObjectAccessible(mHwnd);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLWin32ObjectOwnerAccessible: nsAccessNode implementation
 
 nsresult
 nsHTMLWin32ObjectOwnerAccessible::Shutdown()
 {
   nsAccessibleWrap::Shutdown();
   mNativeAccessible = nsnull;
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTMLWin32ObjectOwnerAccessible: nsIAccessible implementation
-
-NS_IMETHODIMP
-nsHTMLWin32ObjectOwnerAccessible::GetFirstChild(nsIAccessible **aFirstChild)
-{
-  NS_ENSURE_ARG_POINTER(aFirstChild);
-  *aFirstChild = nsnull;
-
-  // Our only child is a nsHTMLWin32ObjectAccessible object.
-  if (!mNativeAccessible) {
-    if (!mHwnd)
-      return NS_OK;
-
-    mNativeAccessible = new nsHTMLWin32ObjectAccessible(mHwnd);
-    NS_ENSURE_TRUE(mNativeAccessible, NS_ERROR_OUT_OF_MEMORY);
-
-    SetFirstChild(mNativeAccessible);
-  }
-
-  *aFirstChild = mNativeAccessible;
-  NS_IF_ADDREF(*aFirstChild);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLWin32ObjectOwnerAccessible::GetLastChild(nsIAccessible **aLastChild)
-{
-  return GetFirstChild(aLastChild);
-}
-
-NS_IMETHODIMP
-nsHTMLWin32ObjectOwnerAccessible::GetChildCount(PRInt32 *aChildCount)
-{
-  NS_ENSURE_ARG_POINTER(aChildCount);
-
-  nsCOMPtr<nsIAccessible> onlyChild;
-  GetFirstChild(getter_AddRefs(onlyChild));
-  *aChildCount = onlyChild ? 1 : 0;
-  return NS_OK;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
 // nsHTMLWin32ObjectOwnerAccessible: nsAccessible implementation
 
 nsresult
 nsHTMLWin32ObjectOwnerAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   NS_ENSURE_ARG_POINTER(aRole);
 
   *aRole = nsIAccessibleRole::ROLE_EMBEDDED_OBJECT;
@@ -129,16 +88,31 @@ nsHTMLWin32ObjectOwnerAccessible::GetSta
   // XXX: No HWND means this is windowless plugin which is not accessible in
   // the meantime.
   if (!mHwnd)
     *aState = nsIAccessibleStates::STATE_UNAVAILABLE;
 
   return rv;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLWin32ObjectOwnerAccessible: nsAccessible protected implementation
+
+void
+nsHTMLWin32ObjectOwnerAccessible::CacheChildren()
+{
+  if (mNativeAccessible) {
+    mChildren.AppendObject(mNativeAccessible);
+
+    nsRefPtr<nsAccessible> nativeAcc =
+      nsAccUtils::QueryObject<nsAccessible>(mNativeAccessible);
+    nativeAcc->SetParent(this);
+  }
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLWin32ObjectAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLWin32ObjectAccessible::nsHTMLWin32ObjectAccessible(void* aHwnd):
 nsLeafAccessible(nsnull, nsnull)
 {
--- a/accessible/src/msaa/nsHTMLWin32ObjectAccessible.h
+++ b/accessible/src/msaa/nsHTMLWin32ObjectAccessible.h
@@ -51,29 +51,28 @@ public:
   // <object> or <embed> exists in the tree, so that get_accNextSibling() etc.
   // will still point to Gecko accessible sibling content. This is necessary
   // because the native plugin accessible doesn't know where it exists in the
   // Mozilla tree, and returns null for previous and next sibling. This would
   // have the effect of cutting off all content after the plugin.
   nsHTMLWin32ObjectOwnerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell, void* aHwnd);
   virtual ~nsHTMLWin32ObjectOwnerAccessible() {}
 
-  // nsIAccessible
-  NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
-  NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
-  NS_IMETHOD GetChildCount(PRInt32 *aChildCount);  // Zero or one child
-
   // nsAccessNode
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
 protected:
+
+  // nsAccessible
+  virtual void CacheChildren();
+
   void* mHwnd;
   nsCOMPtr<nsIAccessible> mNativeAccessible;
 };
 
 /**
   * This class is used only internally, we never! send out an IAccessible linked
   *   back to this object. This class is used to represent a plugin object when
   *   referenced as a child or sibling of another nsAccessible node. We need only
--- a/accessible/src/xforms/nsXFormsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsAccessible.cpp
@@ -100,26 +100,16 @@ nsXFormsAccessible::GetBoundChildElement
 
   aValue.Truncate();
   return NS_OK;
 }
 
 void
 nsXFormsAccessible::CacheSelectChildren(nsIDOMNode *aContainerNode)
 {
-  if (!mWeakShell) {
-    // This node has been shut down
-    mAccChildCount = eChildCountUninitialized;
-    return;
-  }
-
-  if (mAccChildCount != eChildCountUninitialized)
-    return;
-
-  mAccChildCount = 0; // Avoid reentry
   nsIAccessibilityService *accService = GetAccService();
   if (!accService)
     return;
 
   nsCOMPtr<nsIDOMNode> container(aContainerNode);
   if (!container)
     container = mDOMNode;
 
@@ -128,42 +118,33 @@ nsXFormsAccessible::CacheSelectChildren(
 
   if (!children)
     return;
 
   PRUint32 length = 0;
   children->GetLength(&length);
 
   nsCOMPtr<nsIAccessible> accessible;
-  nsRefPtr<nsAccessible> currAccessible, prevAccessible;
+  nsRefPtr<nsAccessible> acc;
 
   PRUint32 childLength = 0;
   for (PRUint32 index = 0; index < length; index++) {
     nsCOMPtr<nsIDOMNode> child;
     children->Item(index, getter_AddRefs(child));
     if (!child)
       continue;
 
     accService->GetAttachedAccessibleFor(child, getter_AddRefs(accessible));
-    currAccessible = nsAccUtils::QueryAccessible(accessible);
-    if (!currAccessible)
+    if (!accessible)
       continue;
 
-    if (childLength == 0)
-      SetFirstChild(accessible);
-
-    currAccessible->SetParent(this);
-    if (prevAccessible) {
-      prevAccessible->SetNextSibling(accessible);
-    }
-    currAccessible.swap(prevAccessible);
-    childLength++;
+    mChildren.AppendObject(accessible);
+    acc = nsAccUtils::QueryObject<nsAccessible>(accessible);
+    acc->SetParent(this);
   }
-
-  mAccChildCount = childLength;
 }
 
 // nsIAccessible
 
 NS_IMETHODIMP
 nsXFormsAccessible::GetValue(nsAString& aValue)
 {
   NS_ENSURE_TRUE(sXFormsService, NS_ERROR_FAILURE);
--- a/accessible/src/xforms/nsXFormsFormControlsAccessible.h
+++ b/accessible/src/xforms/nsXFormsFormControlsAccessible.h
@@ -206,33 +206,39 @@ class nsXFormsChoicesAccessible : public
 public:
   nsXFormsChoicesAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString& aValue);
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
-  void CacheChildren();
+
+protected:
+  // nsAccessible
+  virtual void CacheChildren();
 };
 
 
 /**
  * Accessible object for xforms:select/xforms:select1 of full appearance that
  * may be represented by group of checkboxes or radiogroup.
  */
 
 class nsXFormsSelectFullAccessible : public nsXFormsSelectableAccessible
 {
 public:
   nsXFormsSelectFullAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
-  void CacheChildren();
+
+protected:
+  // nsAccessible
+  virtual void CacheChildren();
 };
 
 
 /**
  * Accessible object for a xforms:item when it is represented by a checkbox.
  * This occurs when the item is contained in a xforms:select with full
  * appearance. Such a xforms:select is represented by a checkgroup.
  */
--- a/accessible/src/xforms/nsXFormsWidgetsAccessible.h
+++ b/accessible/src/xforms/nsXFormsWidgetsAccessible.h
@@ -93,12 +93,13 @@ public:
   NS_IMETHOD GetDescription(nsAString& aDescription);
 
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
 protected:
-  void CacheChildren();
+  // nsAccessible
+  virtual void CacheChildren();
 };
 
 #endif
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp
+++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp
@@ -161,45 +161,29 @@ nsXULColorPickerAccessible::GetRoleInter
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULColorPickerAccessible: protected nsAccessible
 
 void
 nsXULColorPickerAccessible::CacheChildren()
 {
-  if (IsDefunct()) {
-    mAccChildCount = eChildCountUninitialized;
-    return;   // This outer doc node has been shut down
-  }
-
-  if (mAccChildCount != eChildCountUninitialized)
-    return;
-
-  mAccChildCount = 0;  // Avoid reentry
-
   nsCOMPtr<nsIAccessible> menupopupAccessible;
   nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
   walker.GetFirstChild();
 
   while (walker.mState.accessible) {
     PRUint32 role = nsAccUtils::Role(walker.mState.accessible);
 
+    // Get an accessbile for menupopup or panel elements.
     if (role == nsIAccessibleRole::ROLE_ALERT) {
-      // Get an accessbile for menupopup or panel elements.
-      menupopupAccessible = walker.mState.accessible;
-      break;
+      mChildren.AppendObject(walker.mState.accessible);
+      
+      nsRefPtr<nsAccessible> menupopupAcc =
+        nsAccUtils::QueryObject<nsAccessible>(walker.mState.accessible);
+      menupopupAcc->SetParent(this);
+
+      return;
     }
 
     walker.GetNextSibling();
   }
-
-  if (!menupopupAccessible)
-    return;
-
-  SetFirstChild(menupopupAccessible);
-
-  nsRefPtr<nsAccessible> menupopupAcc =
-    nsAccUtils::QueryObject<nsAccessible>(menupopupAccessible);
-  menupopupAcc->SetParent(this);
-
-  mAccChildCount++;
 }
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -181,88 +181,71 @@ nsXULButtonAccessible::GetStateInternal(
 
 void
 nsXULButtonAccessible::CacheChildren()
 {
   // In general XUL button has not accessible children. Nevertheless menu
   // buttons can have button (@type="menu-button") and popup accessibles
   // (@type="menu-button" or @type="menu").
 
-  if (!mWeakShell) {
-    mAccChildCount = eChildCountUninitialized;
-    return;   // This outer doc node has been shut down
-  }
-  if (mAccChildCount == eChildCountUninitialized) {
-    mAccChildCount = 0;  // Avoid reentry
-
-    SetFirstChild(nsnull);
+  // XXX: no children until the button is menu button. Probably it's not
+  // totally correct but in general AT wants to have leaf buttons.
+  nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
 
-    // XXX: no children until the button is menu button. Probably it's not
-    // totally correct but in general AT wants to have leaf buttons.
-    nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+  PRBool isMenu = content->AttrValueIs(kNameSpaceID_None,
+                                       nsAccessibilityAtoms::type,
+                                       nsAccessibilityAtoms::menu,
+                                       eCaseMatters);
 
-    PRBool isMenu = content->AttrValueIs(kNameSpaceID_None,
-                                         nsAccessibilityAtoms::type,
-                                         nsAccessibilityAtoms::menu,
-                                         eCaseMatters);
+  PRBool isMenuButton = isMenu ?
+    PR_FALSE :
+    content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
+                         nsAccessibilityAtoms::menuButton, eCaseMatters);
 
-    PRBool isMenuButton = isMenu ?
-      PR_FALSE :
-      content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
-                           nsAccessibilityAtoms::menuButton, eCaseMatters);
+  if (!isMenu && !isMenuButton)
+    return;
 
-    if (!isMenu && !isMenuButton)
-      return;
-
-    nsCOMPtr<nsIAccessible> buttonAccessible;
-    nsCOMPtr<nsIAccessible> menupopupAccessible;
+  nsCOMPtr<nsIAccessible> buttonAccessible;
+  nsCOMPtr<nsIAccessible> menupopupAccessible;
 
-    nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
-    walker.GetFirstChild();
+  nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
+  walker.GetFirstChild();
 
-    while (walker.mState.accessible) {
-      PRUint32 role = nsAccUtils::Role(walker.mState.accessible);
+  while (walker.mState.accessible) {
+    PRUint32 role = nsAccUtils::Role(walker.mState.accessible);
 
-      if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
-        // Get an accessbile for menupopup or panel elements.
-        menupopupAccessible = walker.mState.accessible;
+    if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
+      // Get an accessbile for menupopup or panel elements.
+      menupopupAccessible = walker.mState.accessible;
 
-      } else if (isMenuButton && role == nsIAccessibleRole::ROLE_PUSHBUTTON) {
-        // Button type="menu-button" contains a real button. Get an accessible
-        // for it. Ignore dropmarker button what is placed as a last child.
-        buttonAccessible = walker.mState.accessible;
-        break;
-      }
-
-      walker.GetNextSibling();
+    } else if (isMenuButton && role == nsIAccessibleRole::ROLE_PUSHBUTTON) {
+      // Button type="menu-button" contains a real button. Get an accessible
+      // for it. Ignore dropmarker button what is placed as a last child.
+      buttonAccessible = walker.mState.accessible;
+      break;
     }
 
-    if (!menupopupAccessible)
-      return;
-
-    SetFirstChild(menupopupAccessible);
+    walker.GetNextSibling();
+  }
 
-    nsRefPtr<nsAccessible> menupopupAcc =
-      nsAccUtils::QueryObject<nsAccessible>(menupopupAccessible);
-    menupopupAcc->SetParent(this);
+  if (!menupopupAccessible)
+    return;
 
-    mAccChildCount++;
+  mChildren.AppendObject(menupopupAccessible);
 
-    if (buttonAccessible) {
-      if (menupopupAcc)
-        menupopupAcc->SetNextSibling(buttonAccessible);
-      else
-        SetFirstChild(buttonAccessible);
+  nsRefPtr<nsAccessible> menupopupAcc =
+    nsAccUtils::QueryObject<nsAccessible>(menupopupAccessible);
+  menupopupAcc->SetParent(this);
 
-      nsRefPtr<nsAccessible> buttonAcc =
-        nsAccUtils::QueryObject<nsAccessible>(buttonAccessible);
-      buttonAcc->SetParent(this);
+  if (buttonAccessible) {
+    mChildren.AppendObject(buttonAccessible);
 
-      mAccChildCount++;
-    }
+    nsRefPtr<nsAccessible> buttonAcc =
+      nsAccUtils::QueryObject<nsAccessible>(buttonAccessible);
+    buttonAcc->SetParent(this);
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULButtonAccessible protected
 
 PRBool
 nsXULButtonAccessible::ContainsMenu()
--- a/accessible/src/xul/nsXULFormControlAccessible.h
+++ b/accessible/src/xul/nsXULFormControlAccessible.h
@@ -71,17 +71,17 @@ public:
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
 protected:
 
   // nsAccessible
-  void CacheChildren();
+  virtual void CacheChildren();
 
   // nsXULButtonAccessible
   PRBool ContainsMenu();
 };
 
 
 /**
  * Used for XUL checkbox.
--- a/accessible/src/xul/nsXULTabAccessible.cpp
+++ b/accessible/src/xul/nsXULTabAccessible.cpp
@@ -231,25 +231,16 @@ nsAccessibleWrap(aNode, aShell)
 /** We are a window*/
 nsresult
 nsXULTabBoxAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   *aRole = nsIAccessibleRole::ROLE_PANE;
   return NS_OK;
 }
 
-#ifdef NEVER
-/** 2 children, tabs, tabpanels */
-NS_IMETHODIMP nsXULTabBoxAccessible::GetChildCount(PRInt32 *_retval)
-{
-  *_retval = 2;
-  return NS_OK;
-}
-#endif
-
 /**
   * XUL Tabs - the s really stands for strip. this is a collection of tab objects
   */
 
 /** Constructor */
 nsXULTabsAccessible::nsXULTabsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
 nsXULSelectableAccessible(aNode, aShell)
 { 
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -216,93 +216,16 @@ nsXULTreeAccessible::GetRoleInternal(PRU
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeAccessible: nsIAccessible implementation
 
 NS_IMETHODIMP
-nsXULTreeAccessible::GetFirstChild(nsIAccessible **aFirstChild)
-{
-  nsAccessible::GetFirstChild(aFirstChild);
-
-  // in normal case, tree's first child should be treecols, if it is not here, 
-  //   use the first row as tree's first child
-  if (*aFirstChild == nsnull) {
-    if (IsDefunct())
-      return NS_ERROR_FAILURE;
-
-    PRInt32 rowCount;
-    mTreeView->GetRowCount(&rowCount);
-    if (rowCount > 0)
-      GetTreeItemAccessible(0, aFirstChild);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessible::GetLastChild(nsIAccessible **aLastChild)
-{
-  NS_ENSURE_ARG_POINTER(aLastChild);
-  *aLastChild = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  PRInt32 rowCount = 0;
-  mTreeView->GetRowCount(&rowCount);
-  if (rowCount > 0) {
-    GetTreeItemAccessible(rowCount - 1, aLastChild);
-
-    if (*aLastChild)
-      return NS_OK;
-  }
-
-  // If there is not any rows, use treecols as tree's last child.
-  return nsAccessible::GetLastChild(aLastChild);
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessible::GetChildCount(PRInt32 *aChildCount)
-{
-  // tree's children count is row count + treecols count.
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsAccessible::GetChildCount(aChildCount);
-
-  if (*aChildCount != eChildCountUninitialized) {
-    PRInt32 rowCount = 0;
-    mTreeView->GetRowCount(&rowCount);
-    *aChildCount += rowCount;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessible::GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild)
-{
-  NS_ENSURE_ARG_POINTER(aChild);
-  *aChild = nsnull;
-
-  PRInt32 childCount = 0;
-  nsresult rv = nsAccessible::GetChildCount(&childCount);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aChildIndex < childCount)
-    return nsAccessible::GetChildAt(aChildIndex, aChild);
-
-  GetTreeItemAccessible(aChildIndex - childCount, aChild);
-  return *aChild ? NS_OK : NS_ERROR_INVALID_ARG;
-}
-
-NS_IMETHODIMP
 nsXULTreeAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) 
 {
   NS_ENSURE_ARG_POINTER(aFocusedChild);
   *aFocusedChild = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
@@ -531,16 +454,66 @@ nsXULTreeAccessible::SelectAllSelection(
       }
     }
   }
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: nsAccessible implementation
+
+nsIAccessible*
+nsXULTreeAccessible::GetChildAt(PRUint32 aIndex)
+{
+  PRInt32 childCount = nsAccessible::GetChildCount();
+  if (childCount == -1)
+    return nsnull;
+
+  if (static_cast<PRInt32>(aIndex) < childCount)
+    return nsAccessible::GetChildAt(aIndex);
+
+  nsCOMPtr<nsIAccessible> child;
+  GetTreeItemAccessible(aIndex - childCount, getter_AddRefs(child));
+  return child;
+}
+
+PRInt32
+nsXULTreeAccessible::GetChildCount()
+{
+  // tree's children count is row count + treecols count.
+  PRInt32 childCount = nsAccessible::GetChildCount();
+  if (childCount == -1)
+    return -1;
+
+  PRInt32 rowCount = 0;
+  mTreeView->GetRowCount(&rowCount);
+  childCount += rowCount;
+
+  return childCount;
+}
+
+PRInt32
+nsXULTreeAccessible::GetIndexOf(nsIAccessible *aChild)
+{
+  if (IsDefunct())
+    return -1;
+
+  nsRefPtr<nsXULTreeItemAccessibleBase> item =
+    nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(aChild);
+
+  // If the given child is not treeitem then it should be treecols accessible.
+  if (!item)
+    return nsAccessible::GetIndexOf(aChild);
+
+  return nsAccessible::GetChildCount() + item->GetRowIndex();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeAccessible: public implementation
 
 void
 nsXULTreeAccessible::GetTreeItemAccessible(PRInt32 aRow,
                                            nsIAccessible** aAccessible)
 {
   *aAccessible = nsnull;
 
@@ -770,77 +743,16 @@ nsXULTreeItemAccessibleBase::GetUniqueID
   *aUniqueID = static_cast<void*>(this);
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessibleBase: nsIAccessible implementation
 
 NS_IMETHODIMP
-nsXULTreeItemAccessibleBase::GetParent(nsIAccessible **aParent)
-{
-  NS_ENSURE_ARG_POINTER(aParent);
-  *aParent = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  if (mParent) {
-    *aParent = mParent;
-    NS_ADDREF(*aParent);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeItemAccessibleBase::GetNextSibling(nsIAccessible **aNextSibling)
-{
-  NS_ENSURE_ARG_POINTER(aNextSibling);
-  *aNextSibling = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsRefPtr<nsXULTreeAccessible> treeAcc =
-    nsAccUtils::QueryAccessibleTree(mParent);
-  NS_ENSURE_STATE(treeAcc);
-
-  PRInt32 rowCount = 0;
-  mTreeView->GetRowCount(&rowCount);
-  if (mRow + 1 >= rowCount)
-    return NS_OK;
-
-  treeAcc->GetTreeItemAccessible(mRow + 1, aNextSibling);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeItemAccessibleBase::GetPreviousSibling(nsIAccessible **aPreviousSibling)
-{
-  NS_ENSURE_ARG_POINTER(aPreviousSibling);
-  *aPreviousSibling = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsRefPtr<nsXULTreeAccessible> treeAcc =
-    nsAccUtils::QueryAccessibleTree(mParent);
-  NS_ENSURE_STATE(treeAcc);
-
-  // Get previous row accessible or tree columns accessible.
-  if (mRow > 0)
-    treeAcc->GetTreeItemAccessible(mRow - 1, aPreviousSibling);
-  else
-    treeAcc->GetFirstChild(aPreviousSibling);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsXULTreeItemAccessibleBase::GetFocusedChild(nsIAccessible **aFocusedChild) 
 {
   NS_ENSURE_ARG_POINTER(aFocusedChild);
   *aFocusedChild = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
@@ -1043,17 +955,17 @@ nsXULTreeItemAccessibleBase::Shutdown()
   mTree = nsnull;
   mTreeView = nsnull;
   mRow = -1;
 
   return nsAccessibleWrap::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULTreeItemAccessibleBase: nsAccessible implementation
+// nsXULTreeItemAccessibleBase: nsAccessible public methods
 
 nsresult
 nsXULTreeItemAccessibleBase::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
@@ -1153,18 +1065,24 @@ nsXULTreeItemAccessibleBase::GetStateInt
   mTree->GetFirstVisibleRow(&firstVisibleRow);
   mTree->GetLastVisibleRow(&lastVisibleRow);
   if (mRow < firstVisibleRow || mRow > lastVisibleRow)
     *aState |= nsIAccessibleStates::STATE_INVISIBLE;
 
   return NS_OK;
 }
 
+nsIAccessible*
+nsXULTreeItemAccessibleBase::GetParent()
+{
+  return IsDefunct() ? nsnull : mParent.get();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULTreeItemAccessibleBase: protected implementation
+// nsXULTreeItemAccessibleBase: nsAccessible protected methods
 
 void
 nsXULTreeItemAccessibleBase::DispatchClickEvent(nsIContent *aContent,
                                                 PRUint32 aActionIndex)
 {
   if (IsDefunct())
     return;
 
@@ -1185,16 +1103,51 @@ nsXULTreeItemAccessibleBase::DispatchCli
     columns->GetPrimaryColumn(getter_AddRefs(column));
     pseudoElm = NS_LITERAL_CSTRING("twisty");
   }
 
   if (column)
     nsCoreUtils::DispatchClickEvent(mTree, mRow, column, pseudoElm);
 }
 
+nsIAccessible*
+nsXULTreeItemAccessibleBase::GetSiblingAtOffset(PRInt32 aOffset,
+                                                nsresult* aError)
+{
+  if (mRow + aOffset < 0)
+    return nsAccessible::GetSiblingAtOffset(mRow + aOffset, aError);
+
+  if (IsDefunct()) {
+    if (aError)
+      *aError = NS_ERROR_FAILURE;
+
+    return nsnull;
+  }
+
+  if (aError)
+    *aError = NS_OK; // fail peacefully
+
+  nsRefPtr<nsXULTreeAccessible> treeAcc =
+    nsAccUtils::QueryAccessibleTree(mParent);
+  if (!treeAcc)
+    return nsnull;
+
+  PRInt32 rowCount = 0;
+  mTreeView->GetRowCount(&rowCount);
+  if (mRow + aOffset >= rowCount)
+    return nsnull;
+
+  nsCOMPtr<nsIAccessible> sibling;
+  treeAcc->GetTreeItemAccessible(mRow + aOffset, getter_AddRefs(sibling));
+  return sibling;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessibleBase: protected implementation
+
 PRBool
 nsXULTreeItemAccessibleBase::IsExpandable()
 {
   PRBool isContainer = PR_FALSE;
   mTreeView->IsContainer(mRow, &isContainer);
   if (isContainer) {
     PRBool isEmpty = PR_FALSE;
     mTreeView->IsContainerEmpty(mRow, &isEmpty);
@@ -1226,43 +1179,16 @@ nsXULTreeItemAccessible(nsIDOMNode *aDOM
 {
   mColumn = nsCoreUtils::GetFirstSensibleColumn(mTree);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessible: nsIAccessible implementation
 
 NS_IMETHODIMP
-nsXULTreeItemAccessible::GetFirstChild(nsIAccessible **aFirstChild)
-{
-  NS_ENSURE_ARG_POINTER(aFirstChild);
-  *aFirstChild = nsnull;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeItemAccessible::GetLastChild(nsIAccessible **aLastChild)
-{
-  NS_ENSURE_ARG_POINTER(aLastChild);
-  *aLastChild = nsnull;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeItemAccessible::GetChildCount(PRInt32 *aChildCount)
-{
-  NS_ENSURE_ARG_POINTER(aChildCount);
-  *aChildCount = 0;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsXULTreeItemAccessible::GetName(nsAString& aName)
 {
   aName.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   mTreeView->GetCellText(mRow, mColumn, aName);
@@ -1333,47 +1259,69 @@ nsXULTreeItemAccessible::RowInvalidated(
   GetName(name);
 
   if (name != mCachedName) {
     nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
     mCachedName = name;
   }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessible: nsAccessible protected implementation
+
+void
+nsXULTreeItemAccessible::CacheChildren()
+{
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////
 //  nsXULTreeColumnsAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTreeColumnsAccessible::
   nsXULTreeColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
   nsXULColumnsAccessible(aDOMNode, aShell)
 {
 }
 
-NS_IMETHODIMP
-nsXULTreeColumnsAccessible::GetNextSibling(nsIAccessible **aNextSibling)
+nsIAccessible*
+nsXULTreeColumnsAccessible::GetSiblingAtOffset(PRInt32 aOffset,
+                                               nsresult* aError)
 {
-  NS_ENSURE_ARG_POINTER(aNextSibling);
-  *aNextSibling = nsnull;
+  if (aOffset < 0)
+    return nsXULColumnsAccessible::GetSiblingAtOffset(aOffset, aError);
+
+  if (IsDefunct()) {
+    if (aError)
+      *aError = NS_ERROR_FAILURE;
+
+    return nsnull;
+  }
+
+  if (aError)
+    *aError = NS_OK; // fail peacefully
 
   nsCOMPtr<nsITreeBoxObject> tree;
   nsCOMPtr<nsITreeView> treeView;
 
   nsCoreUtils::GetTreeBoxObject(mDOMNode, getter_AddRefs(tree));
   if (tree) {
     tree->GetView(getter_AddRefs(treeView));
     if (treeView) {
       PRInt32 rowCount = 0;
       treeView->GetRowCount(&rowCount);
-      if (rowCount > 0) {
+      if (rowCount > 0 && aOffset <= rowCount) {
         nsRefPtr<nsXULTreeAccessible> treeAcc =
           nsAccUtils::QueryAccessibleTree(mParent);
-        NS_ENSURE_STATE(treeAcc);
 
-        treeAcc->GetTreeItemAccessible(0, aNextSibling);
+        if (treeAcc) {
+          nsCOMPtr<nsIAccessible> sibling;
+          treeAcc->GetTreeItemAccessible(aOffset - 1, getter_AddRefs(sibling));
+          return sibling;
+        }
       }
     }
   }
 
-  return NS_OK;
+  return nsnull;
 }
 
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -68,38 +68,36 @@ public:
 
   // nsISupports and cycle collection
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeAccessible,
                                            nsAccessible)
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString& aValue);
-
-  NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
-  NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
-  NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
-  NS_IMETHOD GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild);
-
   NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
 
   // nsIAccessibleSelectable
   NS_DECL_NSIACCESSIBLESELECTABLE
 
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                    PRBool aDeepestChild,
                                    nsIAccessible **aChild);
 
+  virtual nsIAccessible* GetChildAt(PRUint32 aIndex);
+  virtual PRInt32 GetChildCount();
+  virtual PRInt32 GetIndexOf(nsIAccessible *aChild);
+
   // nsXULTreeAccessible
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEACCESSIBLE_IMPL_CID)
 
   /**
    * Return tree item accessible at the givem row. If accessible doesn't exist
    * in the cache then create and cache it.
    *
@@ -173,20 +171,16 @@ public:
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessNode
   NS_IMETHOD GetUniqueID(void **aUniqueID);
 
   // nsIAccessible
-  NS_IMETHOD GetParent(nsIAccessible **aParent);
-  NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
-  NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
-
   NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
 
   NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
                        PRInt32 *aWidth, PRInt32 *aHeight);
 
   NS_IMETHOD SetSelected(PRBool aSelect); 
   NS_IMETHOD TakeFocus();
 
@@ -199,21 +193,27 @@ public:
 
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+  virtual nsIAccessible* GetParent();
 
   // nsXULTreeItemAccessibleBase
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID)
 
   /**
+   * Return row index associated with the accessible.
+   */
+  PRInt32 GetRowIndex() const { return mRow; }
+
+  /**
    * Return cell accessible for the given column. If XUL tree accessible is not
    * accessible table then return null.
    */
   virtual void GetCellAccessible(nsITreeColumn *aColumn,
                                  nsIAccessible **aCellAcc)
     { *aCellAcc = nsnull; }
 
   /**
@@ -221,16 +221,18 @@ public:
    */
   virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx) = 0;
 
 protected:
   enum { eAction_Click = 0, eAction_Expand = 1 };
 
   // nsAccessible
   virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
+  virtual nsIAccessible* GetSiblingAtOffset(PRInt32 aOffset,
+                                            nsresult* aError = nsnull);
 
   // nsXULTreeItemAccessibleBase
 
   /**
    * Return true if the tree item accessible is expandable (contains subrows).
    */
   PRBool IsExpandable();
 
@@ -248,45 +250,47 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeI
  */
 class nsXULTreeItemAccessible : public nsXULTreeItemAccessibleBase
 {
 public:
   nsXULTreeItemAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
                           nsIAccessible *aParent, nsITreeBoxObject *aTree,
                           nsITreeView *aTreeView, PRInt32 aRow);
 
-  // nsIAccessible
-  NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
-  NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
-  NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
-
   NS_IMETHOD GetName(nsAString& aName);
 
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual nsresult Init();
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
 
   // nsXULTreeItemAccessibleBase
   virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx);
 
 protected:
+
+  // nsAccessible
+  virtual void CacheChildren();
+
+  // nsXULTreeItemAccessible
   nsCOMPtr<nsITreeColumn> mColumn;
   nsString mCachedName;
 };
 
 
 /**
  * Accessible class for columns element of XUL tree.
  */
 class nsXULTreeColumnsAccessible : public nsXULColumnsAccessible
 {
 public:
   nsXULTreeColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
 
-  // nsIAccessible
-  NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
+protected:
+
+  // nsAccessible
+  nsIAccessible* GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError = nsnull);
 };
 
 #endif
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -90,25 +90,25 @@ nsXULTreeGridAccessible::GetCaption(nsIA
 NS_IMETHODIMP
 nsXULTreeGridAccessible::GetSummary(nsAString &aSummary)
 {
   aSummary.Truncate();
   return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
 }
 
 NS_IMETHODIMP
-nsXULTreeGridAccessible::GetColumnCount(PRInt32 *acolumnCount)
+nsXULTreeGridAccessible::GetColumnCount(PRInt32 *aColumnCount)
 {
-  NS_ENSURE_ARG_POINTER(acolumnCount);
-  *acolumnCount = 0;
+  NS_ENSURE_ARG_POINTER(aColumnCount);
+  *aColumnCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  *acolumnCount = nsCoreUtils::GetSensiblecolumnCount(mTree);
+  *aColumnCount = nsCoreUtils::GetSensibleColumnCount(mTree);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeGridAccessible::GetRowCount(PRInt32 *arowCount)
 {
   NS_ENSURE_ARG_POINTER(arowCount);
   *arowCount = nsnull;
@@ -631,87 +631,16 @@ NS_INTERFACE_MAP_STATIC_AMBIGUOUS(nsXULT
 NS_INTERFACE_MAP_END_INHERITING(nsXULTreeItemAccessibleBase)
 
 NS_IMPL_ADDREF_INHERITED(nsXULTreeGridRowAccessible,
                          nsXULTreeItemAccessibleBase)
 NS_IMPL_RELEASE_INHERITED(nsXULTreeGridRowAccessible,
                           nsXULTreeItemAccessibleBase)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULTreeGridRowAccessible: nsIAccessible implementation
-
-NS_IMETHODIMP
-nsXULTreeGridRowAccessible::GetFirstChild(nsIAccessible **aFirstChild)
-{
-  NS_ENSURE_ARG_POINTER(aFirstChild);
-  *aFirstChild = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
-  NS_ASSERTION(column, "No column for table grid!");
-  if (!column)
-    return NS_ERROR_FAILURE;
-
-  GetCellAccessible(column, aFirstChild);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeGridRowAccessible::GetLastChild(nsIAccessible **aLastChild)
-{
-  NS_ENSURE_ARG_POINTER(aLastChild);
-  *aLastChild = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetLastSensibleColumn(mTree);
-  NS_ASSERTION(column, "No column for table grid!");
-  if (!column)
-    return NS_ERROR_FAILURE;
-
-  GetCellAccessible(column, aLastChild);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeGridRowAccessible::GetChildCount(PRInt32 *aChildCount)
-{
-  NS_ENSURE_ARG_POINTER(aChildCount);
-  *aChildCount = 0;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  *aChildCount = nsCoreUtils::GetSensiblecolumnCount(mTree);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeGridRowAccessible::GetChildAt(PRInt32 aChildIndex,
-                                       nsIAccessible **aChild)
-{
-  NS_ENSURE_ARG_POINTER(aChild);
-  *aChild = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsITreeColumn> column =
-    nsCoreUtils::GetSensibleColumnAt(mTree, aChildIndex);
-  if (!column)
-    return NS_ERROR_INVALID_ARG;
-
-  GetCellAccessible(column, aChild);
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridRowAccessible: nsAccessNode implementation
 
 nsresult
 nsXULTreeGridRowAccessible::Shutdown()
 {
   ClearCache(mAccessNodeCache);
   return nsXULTreeItemAccessibleBase::Shutdown();
 }
@@ -755,16 +684,53 @@ nsXULTreeGridRowAccessible::GetChildAtPo
   // Return if we failed to find tree cell in the row for the given point.
   if (row != mRow || !column)
     return NS_OK;
 
   GetCellAccessible(column, aChild);
   return NS_OK;
 }
 
+nsIAccessible*
+nsXULTreeGridRowAccessible::GetChildAt(PRUint32 aIndex)
+{
+  if (IsDefunct())
+    return nsnull;
+
+  nsCOMPtr<nsITreeColumn> column =
+    nsCoreUtils::GetSensibleColumnAt(mTree, aIndex);
+  if (!column)
+    return nsnull;
+
+  nsCOMPtr<nsIAccessible> cell;
+  GetCellAccessible(column, getter_AddRefs(cell));
+  return cell;
+}
+
+PRInt32
+nsXULTreeGridRowAccessible::GetChildCount()
+{
+  if (IsDefunct())
+    return -1;
+
+  return nsCoreUtils::GetSensibleColumnCount(mTree);
+}
+
+PRInt32
+nsXULTreeGridRowAccessible::GetIndexOf(nsIAccessible *aChild)
+{
+  if (IsDefunct())
+    return -1;
+
+  nsRefPtr<nsXULTreeGridCellAccessible> cell =
+    nsAccUtils::QueryObject<nsXULTreeGridCellAccessible>(aChild);
+
+  return cell ? cell->GetColumnIndex() : -1;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridRowAccessible: nsXULTreeItemAccessibleBase implementation
 
 void
 nsXULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn,
                                               nsIAccessible** aAccessible)
 {
   NS_PRECONDITION(aColumn, "No tree column!");
@@ -813,16 +779,23 @@ nsXULTreeGridRowAccessible::RowInvalidat
           nsAccUtils::QueryObject<nsXULTreeGridCellAccessible>(cellAccessible);
 
         cellAcc->CellInvalidated();
       }
     }
   }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridRowAccessible: nsAccessible protected implementation
+
+void
+nsXULTreeGridRowAccessible::CacheChildren()
+{
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTreeGridCellAccessible::
 nsXULTreeGridCellAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
                             nsXULTreeGridRowAccessible *aRowAcc,
@@ -853,74 +826,16 @@ nsXULTreeGridCellAccessible::GetUniqueID
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: nsIAccessible implementation
 
 NS_IMETHODIMP
-nsXULTreeGridCellAccessible::GetParent(nsIAccessible **aParent)
-{
-  NS_ENSURE_ARG_POINTER(aParent);
-  *aParent = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  if (mParent) {
-    *aParent = mParent;
-    NS_ADDREF(*aParent);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeGridCellAccessible::GetNextSibling(nsIAccessible **aNextSibling)
-{
-  NS_ENSURE_ARG_POINTER(aNextSibling);
-  *aNextSibling = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsITreeColumn> nextColumn =
-    nsCoreUtils::GetNextSensibleColumn(mColumn);
-  if (!nextColumn)
-    return NS_OK;
-
-  nsRefPtr<nsXULTreeItemAccessibleBase> rowAcc =
-    nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(mParent);
-  rowAcc->GetCellAccessible(nextColumn, aNextSibling);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeGridCellAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling)
-{
-  NS_ENSURE_ARG_POINTER(aPreviousSibling);
-  *aPreviousSibling = nsnull;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsITreeColumn> nextColumn =
-    nsCoreUtils::GetPreviousSensibleColumn(mColumn);
-  if (!nextColumn)
-    return NS_OK;
-
-  nsRefPtr<nsXULTreeItemAccessibleBase> rowAcc =
-    nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(mParent);
-  rowAcc->GetCellAccessible(nextColumn, aPreviousSibling);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsXULTreeGridCellAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) 
 {
   NS_ENSURE_ARG_POINTER(aFocusedChild);
   *aFocusedChild = nsnull;
 
   return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
 }
 
@@ -1214,17 +1129,17 @@ nsXULTreeGridCellAccessible::Init()
     mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
   else
     mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULTreeGridCellAccessible: nsAccessible implementation
+// nsXULTreeGridCellAccessible: nsAccessible public implementation
 
 nsresult
 nsXULTreeGridCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
@@ -1302,16 +1217,22 @@ nsXULTreeGridCellAccessible::GetStateInt
     mTreeView->GetCellValue(mRow, mColumn, checked);
     if (checked.EqualsIgnoreCase("true"))
       *aStates |= nsIAccessibleStates::STATE_CHECKED;
   }
 
   return NS_OK;
 }
 
+nsIAccessible*
+nsXULTreeGridCellAccessible::GetParent()
+{
+  return IsDefunct() ? nsnull : mParent.get();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: public implementation
 
 PRInt32
 nsXULTreeGridCellAccessible::GetColumnIndex() const
 {
   PRInt32 index = 0;
   nsCOMPtr<nsITreeColumn> column = mColumn;
@@ -1347,28 +1268,70 @@ nsXULTreeGridCellAccessible::CellInvalid
   mTreeView->GetCellText(mRow, mColumn, textEquiv);
   if (mCachedTextEquiv != textEquiv) {
     nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
     mCachedTextEquiv = textEquiv;
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULTreeGridCellAccessible: protected implementation
+// nsXULTreeGridCellAccessible: nsAccessible protected implementation
+
+nsIAccessible*
+nsXULTreeGridCellAccessible::GetSiblingAtOffset(PRInt32 aOffset,
+                                                nsresult* aError)
+{
+  if (IsDefunct()) {
+    if (aError)
+      *aError = NS_ERROR_FAILURE;
+
+    return nsnull;
+  }
+
+  if (aError)
+    *aError = NS_OK; // fail peacefully
+
+  nsCOMPtr<nsITreeColumn> columnAtOffset(mColumn), column;
+  if (aOffset < 0) {
+    for (PRInt32 index = aOffset; index < 0 && columnAtOffset; index++) {
+      column = nsCoreUtils::GetPreviousSensibleColumn(columnAtOffset);
+      column.swap(columnAtOffset);
+    }
+  } else {
+    for (PRInt32 index = aOffset; index > 0 && columnAtOffset; index--) {
+      column = nsCoreUtils::GetNextSensibleColumn(columnAtOffset);
+      column.swap(columnAtOffset);
+    }
+  }
+
+  if (!columnAtOffset)
+    return nsnull;
+
+  nsRefPtr<nsXULTreeItemAccessibleBase> rowAcc =
+    nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(mParent);
+
+  nsCOMPtr<nsIAccessible> sibling;
+  rowAcc->GetCellAccessible(columnAtOffset, getter_AddRefs(sibling));
+
+  return sibling;
+}
 
 void
 nsXULTreeGridCellAccessible::DispatchClickEvent(nsIContent *aContent,
                                                 PRUint32 aActionIndex)
 {
   if (IsDefunct())
     return;
 
   nsCoreUtils::DispatchClickEvent(mTree, mRow, mColumn);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridCellAccessible: protected implementation
+
 PRBool
 nsXULTreeGridCellAccessible::IsEditable() const
 {
   // XXX: logic corresponds to tree.xml, it's preferable to have interface
   // method to check it.
   PRBool isEditable = PR_FALSE;
   nsresult rv = mTreeView->IsEditable(mRow, mColumn, &isEditable);
   if (NS_FAILED(rv) || !isEditable)
--- a/accessible/src/xul/nsXULTreeGridAccessible.h
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -81,36 +81,39 @@ public:
                              nsIAccessible *aParent, nsITreeBoxObject *aTree,
                              nsITreeView *aTreeView, PRInt32 aRow);
 
   // nsISupports and cycle collection
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeGridRowAccessible,
                                            nsAccessible)
 
-  // nsIAccessible
-  NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
-  NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
-  NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
-  NS_IMETHOD GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild);
-
   // nsAccessNode
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                    PRBool aDeepestChild,
                                    nsIAccessible **aChild);
 
+  virtual nsIAccessible* GetChildAt(PRUint32 aIndex);
+  virtual PRInt32 GetChildCount();
+  virtual PRInt32 GetIndexOf(nsIAccessible *aChild);
+
   // nsXULTreeItemAccessibleBase
   virtual void GetCellAccessible(nsITreeColumn *aColumn, nsIAccessible **aCell);
   virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx);
 
 protected:
+
+  // nsAccessible
+  virtual void CacheChildren();
+
+  // nsXULTreeItemAccessibleBase
   nsAccessNodeHashtable mAccessNodeCache;
 };
 
 
 /**
  * Represents an accessible for XUL tree cell in the case when XUL tree has
  * multiple columns.
  */
@@ -134,20 +137,16 @@ public:
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessNode
   NS_IMETHOD GetUniqueID(void **aUniqueID);
 
   // nsIAccessible
-  NS_IMETHOD GetParent(nsIAccessible **aParent);
-  NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
-  NS_IMETHOD GetPreviousSibling(nsIAccessible **aPrevSibling);
-
   NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
 
   NS_IMETHOD GetName(nsAString& aName);
   NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
                        PRInt32 *aWidth, PRInt32 *aHeight);
 
   NS_IMETHOD GetNumActions(PRUint8 *aCount);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
@@ -160,32 +159,36 @@ public:
   virtual PRBool IsDefunct();
   virtual nsresult Init();
 
   // nsAccessible
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
+  virtual nsIAccessible* GetParent();
+
   // nsXULTreeGridCellAccessible
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID)
 
   /**
    * Return index of the column.
    */
   PRInt32 GetColumnIndex() const;
 
   /**
    * Fire name or state change event if the accessible text or value has been
    * changed.
    */
   void CellInvalidated();
 
 protected:
   // nsAccessible
+  virtual nsIAccessible* GetSiblingAtOffset(PRInt32 aOffset,
+                                            nsresult* aError = nsnull);
   virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
 
   // nsXULTreeGridCellAccessible
 
   /**
    * Return true if value of cell can be modified.
    */
   PRBool IsEditable() const;
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -37,17 +37,17 @@
 # ***** END LICENSE BLOCK *****
 
 DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible
 
-DIRS	= tree
+DIRS	= tree selectable
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		letters.gif \
 		moz.png \
 		$(topsrcdir)/content/media/test/bug461281.ogg \
@@ -103,24 +103,23 @@ include $(topsrcdir)/config/rules.mk
 		test_events_focusdoc.html \
 		test_events_mutation.html \
 		test_events_scroll.xul \
 		test_events_tree.xul \
 		test_events_valuechange.html \
 		test_groupattrs.xul \
 		test_groupattrs.html \
 		test_invalidate_accessnode.html \
-		test_invalidate_elmli.html \
 		test_name.html \
 		test_name.xul \
 		test_name_button.html \
 		test_name_link.html \
 		test_name_markup.html \
+		test_name_nsApplicationAcc.html \
 		test_name_nsRootAcc.xul \
-		test_nsIAccessible_applicationAccessible.html \
 	$(warning test_nsIAccessible_comboboxes.xul temporarily disabled) \
  		test_nsIAccessible_selects.html \
 		test_nsIAccessible_focus.html \
 		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleEditableText.html \
 		test_nsIAccessibleHyperLink.html \
 		test_nsIAccessibleHyperLink.xul \
 		test_nsIAccessibleHyperText.html \
@@ -128,17 +127,16 @@ include $(topsrcdir)/config/rules.mk
 		test_nsIAccessNode_utils.html \
 		test_nsOuterDocAccessible.html \
  		test_objectattrs.html \
 		test_relations.html \
 		test_relations.xul \
 		test_relations_tree.xul \
 		test_role_nsHyperTextAcc.html \
 		test_role_table_cells.html \
-		test_selectable_tree.xul \
 		test_states.html \
 		test_states_doc.html \
 		test_states_docarticle.html \
 		test_states_editablebody.html \
 		test_states_frames.html \
 		test_states_popup.xul \
 		test_states_tree.xul \
 		test_table_1.html \
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -266,16 +266,45 @@ function getRootAccessible(aAccOrElmOrID
 
     acc = parent;
   }
 
   return null;
 }
 
 /**
+ * Return application accessible.
+ */
+function getApplicationAccessible()
+{
+  var acc = getAccessible(document), parent = null;
+  while (acc) {
+
+    try {
+      parent = acc.parent;
+    } catch (e) {
+      ok(false, "Can't get a parent for " + prettyName(acc));
+      return null;
+    }
+
+    if (!parent) {
+      if (acc.role == ROLE_APP_ROOT)
+        return acc;
+
+      ok(false, "No application accessible!");
+      return null;
+    }
+
+    acc = parent;
+  }
+
+  return null;
+}
+
+/**
  * Run through accessible tree of the given identifier so that we ensure
  * accessible tree is created.
  */
 function ensureAccessibleTree(aAccOrElmOrID)
 {
   var acc = getAccessible(aAccOrElmOrID);
   if (!acc)
     return;
@@ -351,16 +380,22 @@ function testAccessibleTree(aAccOrElmOrI
       for (var i = 0; i < children.length; i++) {
         var child = children.queryElementAt(i, nsIAccessible);
 
         // nsIAccessible::parent
         var parent = null;
         try { parent = child.parent; } catch (e) {}
         is(parent, acc, "Wrong parent of " + prettyName(child));
 
+        // nsIAccessible::indexInParent
+        var indexInParent = -1;
+        try { indexInParent = child.indexInParent; } catch(e) {}
+        is(indexInParent, i,
+           "Wrong index in parent of " + prettyName(child));
+
         // nsIAccessible::nextSibling
         var expectedNextSibling = (i < childCount - 1) ?
           children.queryElementAt(i + 1, nsIAccessible) : null;
         var nextSibling = null;
         try { nextSibling = child.nextSibling; } catch (e) {}
         is(nextSibling, expectedNextSibling,
            "Wrong next sibling of " + prettyName(child));
 
@@ -374,16 +409,94 @@ function testAccessibleTree(aAccOrElmOrI
 
         // Go down through subtree
         testAccessibleTree(child, aAccTree.children[i]);
       }
     }
   }
 }
 
+/**
+ * Test accessible tree for defunct accessible.
+ *
+ * @param  aAcc       [in] the defunct accessible
+ * @param  aNodeOrId  [in] the DOM node identifier for the defunct accessible
+ */
+function testDefunctAccessible(aAcc, aNodeOrId)
+{
+  if (aNodeOrId)
+    ok(!isAccessible(aNodeOrId),
+       "Accessible for " + aNodeOrId + " wasn't properly shut down!");
+
+  var msg = " doesn't fail for shut down accessible " + prettyName(aNodeOrId) + "!";
+
+  // firstChild
+  var success = false;
+  try {
+    aAcc.firstChild;
+  } catch (e) {
+    success = (e.result == Components.results.NS_ERROR_FAILURE)
+  }
+  ok(success, "firstChild" + msg);
+
+  // lastChild
+  success = false;
+  try {
+    aAcc.lastChild;
+  } catch (e) {
+    success = (e.result == Components.results.NS_ERROR_FAILURE)
+  }
+  ok(success, "lastChild" + msg);
+
+  // childCount
+  success = false;
+  try {
+    aAcc.childCount;
+  } catch (e) {
+    success = (e.result == Components.results.NS_ERROR_FAILURE)
+  }
+  ok(success, "childCount" + msg);
+
+  // children
+  success = false;
+  try {
+    aAcc.children;
+  } catch (e) {
+    success = (e.result == Components.results.NS_ERROR_FAILURE)
+  }
+  ok(success, "children" + msg);
+
+  // nextSibling
+  success = false;
+  try {
+    aAcc.nextSibling;
+  } catch (e) {
+    success = (e.result == Components.results.NS_ERROR_FAILURE);
+  }
+  ok(success, "nextSibling" + msg);
+
+  // previousSibling
+  success = false;
+  try {
+    aAcc.previousSibling;
+  } catch (e) {
+    success = (e.result == Components.results.NS_ERROR_FAILURE);
+  }
+  ok(success, "previousSibling" + msg);
+
+  // parent
+  success = false;
+  try {
+    aAcc.parent;
+  } catch (e) {
+    success = (e.result == Components.results.NS_ERROR_FAILURE);
+  }
+  ok(success, "parent" + msg);
+}
+
 
 /**
  * Convert role to human readable string.
  */
 function roleToString(aRole)
 {
   return gAccRetrieval.getStringRole(aRole);
 }
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -3,16 +3,17 @@
 
 const ROLE_ALERT = nsIAccessibleRole.ROLE_ALERT;
 const ROLE_APPLICATION = nsIAccessibleRole.ROLE_APPLICATION;
 const ROLE_APP_ROOT = nsIAccessibleRole.ROLE_APP_ROOT;
 const ROLE_AUTOCOMPLETE = nsIAccessibleRole.ROLE_AUTOCOMPLETE;
 const ROLE_BUTTONDROPDOWNGRID = nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID;
 const ROLE_CAPTION = nsIAccessibleRole.ROLE_CAPTION;
 const ROLE_CELL = nsIAccessibleRole.ROLE_CELL;
+const ROLE_CHECKBUTTON = nsIAccessibleRole.ROLE_CHECKBUTTON;
 const ROLE_CHROME_WINDOW = nsIAccessibleRole.ROLE_CHROME_WINDOW;
 const ROLE_COMBOBOX = nsIAccessibleRole.ROLE_COMBOBOX;
 const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
 const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
 const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
 const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
 const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
 const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
@@ -35,26 +36,29 @@ const ROLE_NOTHING = nsIAccessibleRole.R
 const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION;
 const ROLE_OUTLINE = nsIAccessibleRole.ROLE_OUTLINE;
 const ROLE_OUTLINEITEM = nsIAccessibleRole.ROLE_OUTLINEITEM;
 const ROLE_PARAGRAPH = nsIAccessibleRole.ROLE_PARAGRAPH;
 const ROLE_PARENT_MENUITEM = nsIAccessibleRole.ROLE_PARENT_MENUITEM;
 const ROLE_PASSWORD_TEXT = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
 const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
 const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
+const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
 const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
 const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
 const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
+const ROLE_SEPARATOR = nsIAccessibleRole.ROLE_SEPARATOR;
 const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
 const ROLE_STATICTEXT = nsIAccessibleRole.ROLE_STATICTEXT;
 const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
 const ROLE_TEXT_CONTAINER = nsIAccessibleRole.ROLE_TEXT_CONTAINER;
 const ROLE_TEXT_LEAF = nsIAccessibleRole.ROLE_TEXT_LEAF;
 const ROLE_TOGGLE_BUTTON = nsIAccessibleRole.ROLE_TOGGLE_BUTTON;
 const ROLE_TREE_TABLE = nsIAccessibleRole.ROLE_TREE_TABLE;
+const ROLE_WHITESPACE = nsIAccessibleRole.ROLE_WHITESPACE;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Public methods
 
 /**
  * Test that the role of the given accessible is the role passed in.
  *
  * @param aAccOrElmOrID  the accessible, DOM element or ID to be tested.
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/selectable/Makefile.in
@@ -0,0 +1,55 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2009
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either 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/selectable
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES =\
+		test_aria.html \
+		test_select.html \
+		test_tree.xul \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/selectable/test_aria.html
@@ -0,0 +1,120 @@
+<html>
+
+<head>
+  <title>nsIAccessibleSelectable ARIA widgets testing</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  </style>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var id = "list1";
+      ok(isAccessible(id, [nsIAccessibleSelectable]),
+         "No selectable accessible for " + id);
+
+      id = "listbox1";
+      ok(isAccessible(id, [nsIAccessibleSelectable]),
+         "No selectable accessible for " + id);
+
+      id = "listbox2";
+      ok(isAccessible(id, [nsIAccessibleSelectable]),
+         "No selectable accessible for " + id);
+
+      id = "grid1";
+      ok(isAccessible(id, [nsIAccessibleSelectable]),
+         "No selectable accessible for " + id);
+
+      id = "tree1";
+      ok(isAccessible(id, [nsIAccessibleSelectable]),
+         "No selectable accessible for " + id);
+
+      id = "treegrid1";
+      ok(isAccessible(id, [nsIAccessibleSelectable]),
+         "No selectable accessible for " + id);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=530014"
+     title="ARIA single selectable widget should implement nsIAccessibleSelectable">
+    Mozilla Bug 530014
+  </a><br>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div role="list" id="list1">
+    <div role="listitem">item1</div>
+    <div role="listitem">item2</div>
+  </div>
+
+  <div role="listbox" id="listbox1">
+    <div role="listitem">item1</div>
+    <div role="listitem">item2</div>
+  </div>
+
+  <div role="listbox" id="listbox2" aria-multiselectable="true">
+    <div role="listitem">item1</div>
+    <div role="listitem">item2</div>
+  </div>
+
+  <div role="grid" id="grid1">
+    <div role="row">
+      <span role="gridcell">cell</span>
+      <span role="gridcell">cell</span>
+    </div>
+    <div role="row">
+      <span role="gridcell">cell</span>
+      <span role="gridcell">cell</span>
+    </div>
+  </div>
+
+  <div role="tree" id="tree1">
+    <div role="treeitem">
+      item1
+      <div role="group">
+        <div role="treeitem">item1.1</div>
+      </div>
+    </div>
+    <div>item2</div>
+  </div>
+
+  <div role="treegrid" id="treegrid1">
+    <div role="row" aria-level="1">
+      <span role="gridcell">cell</span>
+      <span role="gridcell">cell</span>
+    </div>
+    <div role="row" aria-level="2">
+      <span role="gridcell">cell</span>
+      <span role="gridcell">cell</span>
+    </div>
+    <div role="row" aria-level="1">
+      <span role="gridcell">cell</span>
+      <span role="gridcell">cell</span>
+    </div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/selectable/test_select.html
@@ -0,0 +1,66 @@
+<html>
+
+<head>
+  <title>nsIAccessibleSelectable HTML select testing</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  </style>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+
+    function doTest()
+    {
+      var combobox = getAccessible("combobox");
+      var comboboxList = combobox.firstChild;
+      ok(isAccessible(comboboxList, [nsIAccessibleSelectable]),
+         "No selectable accessible for list of " + id);
+
+      var id = "listbox";
+      ok(isAccessible(id, [nsIAccessibleSelectable]),
+         "No selectable accessible for " + id);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=530014"
+     title="ARIA single selectable widget should implement nsIAccessibleSelectable">
+    Mozilla Bug 530014
+  </a><br>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <select id="combobox">
+    <option>option</option>
+    <option>option</option>
+  </select>
+
+  <select id="listbox" size="4">
+    <option>option</option>
+    <option>option</option>
+  </select>
+
+</body>
+</html>
rename from accessible/tests/mochitest/test_selectable_tree.xul
rename to accessible/tests/mochitest/selectable/test_tree.xul
--- a/accessible/tests/mochitest/test_events_doc.html
+++ b/accessible/tests/mochitest/test_events_doc.html
@@ -42,17 +42,22 @@
     }
 
     function openDialogWnd(aURL)
     {
       // Get application root accessible.
       var docAcc = getAccessible(document);
       while (docAcc) {
         this.mRootAcc = docAcc;
-        docAcc = docAcc.parent;
+        try {
+          docAcc = docAcc.parent;
+        } catch (e) {
+          ok(false, "Can't get parent for " + prettyName(docAcc));
+          throw e;
+        }
       }
 
       this.eventSeq = [
         new invokerChecker(EVENT_REORDER, this.mRootAcc)
       ];
 
       this.invoke = function openDialogWnd_invoke()
       {
deleted file mode 100644
--- a/accessible/tests/mochitest/test_invalidate_elmli.html
+++ /dev/null
@@ -1,168 +0,0 @@
-<!DOCTYPE html>
-<html>
-
-<head>
-  <title>Test HTML li and listitem bullet accessible cache</title>
-  <link rel="stylesheet" type="text/css"
-        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
-  <script type="application/javascript"
-          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
-  <script type="application/javascript"
-          src="chrome://mochikit/content/a11y/accessible/events.js"></script>
-
-  <script type="application/javascript">
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Helpers
-
-    function testDefunctAccessible(aAcc, aNodeOrId)
-    {
-      if (aNodeOrId)
-        ok(!isAccessible(aNodeOrId),
-           "Accessible for " + aNodeOrId + " wasn't properly shut down!");
-
-      ok(!aAcc.firstChild, "There is first child for shut down accessible!");
-      ok(!aAcc.lastChild, "There is last child for shut down accessible!");
-      ok(!aAcc.children.length, "There are children for shut down accessible!");
-
-      // nextSibling
-      var success = false;
-      try {
-        aAcc.nextSibling;
-      } catch (e) {
-        success = (e.result == Components.results.NS_ERROR_FAILURE);
-      }
-
-      ok(success, "There is next sibling for shut down accessible!");
-
-      // previousSibling
-      var success = false;
-      try {
-        aAcc.previousSibling;
-      } catch (e) {
-        success = (e.result == Components.results.NS_ERROR_FAILURE);
-      }
-
-      ok(success, "There is previous sibling for shut down accessible!");
-
-      // parent
-      var success = false;
-      try {
-        aAcc.parent;
-      } catch (e) {
-        success = (e.result == Components.results.NS_ERROR_FAILURE);
-      }
-
-      ok(success, "There is parent for shut down accessible!");
-    }
-
-    function testLiAccessibleTree()
-    {
-      // Test accessible tree.
-      var accTree = {
-        role: ROLE_LISTITEM,
-        children: [
-          {
-            role: ROLE_STATICTEXT,
-            children: []
-          },
-          {
-            role: ROLE_TEXT_LEAF,
-            children: []
-          }
-        ]
-      };
-
-      testAccessibleTree("li", accTree);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Sequence item processors
-
-    function hideProcessor()
-    {
-      this.liNode = getNode("li");
-      this.li = getAccessible(this.liNode);
-      this.bullet = this.li.firstChild;
-
-      this.process = function hideProcessor_process()
-      {
-        this.liNode.style.display = "none";
-      }
-
-      this.onProcessed = function hideProcessor_onProcessed()
-      {
-        window.setTimeout(
-          function(aArg1, aArg2)
-          {
-            testDefunctAccessible(aArg1, aArg2);
-            gSequence.processNext();
-          },
-          0, this.li, this.liNode
-        );
-      }
-    };
-
-    function showProcessor()
-    {
-      this.liNode = getNode("li");
-
-      this.process = function showProcessor_process()
-      {
-        this.liNode.style.display = "list-item";
-      }
-
-      this.onProcessed = function showProcessor_onProcessed()
-      {
-        testLiAccessibleTree();
-        SimpleTest.finish();
-      }
-    };
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Test
-
-    var gSequence = null;
-
-    function doTest()
-    {
-      testLiAccessibleTree();
-
-      gSequence = new sequence();
-
-      gSequence.append(new hideProcessor(), EVENT_HIDE, getAccessible("li"),
-                       "hide HTML li");
-      gSequence.append(new showProcessor(), EVENT_SHOW, getNode("li"),
-                       "show HTML li");
-
-      gSequence.processNext(); // SimpleTest.finish() will be called in the end
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTest);
-  </script>
-</head>
-<body>
-
-  <a target="_blank"
-     title="setParent shouldn't be virtual"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=496783">Mozilla Bug 496783</a>
-
-  <p id="display"></p>
-  <div id="content" style="display: none"></div>
-  <pre id="test">
-  </pre>
-
-  <ul>
-    <li id="li">item1</li>
-  </ul>
-</body>
-</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_name_nsApplicationAcc.html
@@ -0,0 +1,61 @@
+<html>
+
+<head>
+  <title>application accessible name</title>
+  <link rel="stylesheet" type="text/css" 
+         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+        var accessible = getApplicationAccessible();
+        if (!accessible) {
+          SimpleTest.finish();
+          return;
+        }
+
+        var bundleServ = Components.classes["@mozilla.org/intl/stringbundle;1"]
+                         .getService(Components.interfaces.nsIStringBundleService);
+        var bundle = bundleServ.createBundle("chrome://branding/locale/brand.properties");
+
+        var applicationName = "";
+
+        try {
+            applicationName = bundle.GetStringFromName("brandShortName");
+        }  catch(e) {
+        }
+
+        if (applicationName == "")
+            applicationName = "Gecko based application";
+
+        is (accessible.name, applicationName, "wrong application accessible name");
+
+        SimpleTest.finish();
+    }
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+  </head>
+  <body>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=456121"
+    title="nsApplicationAccessible::GetName does not return a default value when brand.properties does not exist">
+    Mozilla Bug 454211
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  </body>
+</html>
deleted file mode 100644
--- a/accessible/tests/mochitest/test_nsIAccessible_applicationAccessible.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<html>
-
-<head>
-  <title>application accessible name</title>
-  <link rel="stylesheet" type="text/css" 
-         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
-   </script>
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/a11y/accessible/common.js" ></script>
-
-  <script type="application/javascript">
-    function doTest()
-    {
-        var accessible = getAccessible(document);
-        while (accessible && accessible.parent) {
-            accessible = accessible.parent;
-        }
-
-        if (!accessible) {
-            SimpleTest.finish();
-            return;
-        }
-
-        var bundleServ = Components.classes["@mozilla.org/intl/stringbundle;1"]
-                         .getService(Components.interfaces.nsIStringBundleService);
-        var bundle = bundleServ.createBundle("chrome://branding/locale/brand.properties");
-
-        var applicationName = "";
-
-        try {
-            applicationName = bundle.GetStringFromName("brandShortName");
-        }  catch(e) {
-        }
-
-        if (applicationName == "")
-            applicationName = "Gecko based application";
-
-        is (accessible.name, applicationName, "wrong application accessible name");
-
-        SimpleTest.finish();
-    }
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTest);
-  </script>
-  </head>
-  <body>
-  <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=456121"
-    title="nsApplicationAccessible::GetName does not return a default value when brand.properties does not exist">
-    Mozilla Bug 454211
-  </a>
-
-  <p id="display"></p>
-  <div id="content" style="display: none"></div>
-  <pre id="test">
-  </pre>
-
-  </body>
-</html>
--- a/accessible/tests/mochitest/test_table_headers.html
+++ b/accessible/tests/mochitest/test_table_headers.html
@@ -114,16 +114,42 @@
           cell: "table3_cell_2",
           rowHeaderCells: [],
           columnHeaderCells: [ "table3_ch_2" ]
         }
       ];
 
       testHeaderCells(headerInfoMap);
 
+      //////////////////////////////////////////////////////////////////////////
+      // table consisted of one column
+
+      headerInfoMap = [
+        {
+          cell: "table4_cell",
+          rowHeaderCells: [],
+          columnHeaderCells: [ "table4_ch" ]
+        }
+      ];
+
+      testHeaderCells(headerInfoMap);
+
+      //////////////////////////////////////////////////////////////////////////
+      // table consisted of one row
+
+      headerInfoMap = [
+        {
+          cell: "table5_cell",
+          rowHeaderCells: [ "table5_rh" ],
+          columnHeaderCells: [ ]
+        }
+      ];
+
+      testHeaderCells(headerInfoMap);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 
@@ -195,10 +221,30 @@
       <td id="table3_cell_1" headers="table3_ch_1">cell1</td>
       <td id="table3_cell_2" headers="table3_ch_2">cell2</td>
     </tr>
     <tr>
       <td id="table3_ch_1" scope="col">col1</td>
       <td id="table3_ch_2" scope="col">col2</td>
     </tr>
   </table>
+
+  <table id="table4">
+    <thead>
+      <tr>
+        <th id="table4_ch">colheader</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td id="table4_cell">bla</td>
+      </tr>
+    </tbody>
+  </table>
+
+  <table id="table5">
+    <tr>
+      <th id="table5_rh">rowheader</th>
+      <td id="table5_cell">cell</td>
+    </tr>
+  </table>
 </body>
 </html>
--- a/accessible/tests/mochitest/tree/Makefile.in
+++ b/accessible/tests/mochitest/tree/Makefile.in
@@ -45,17 +45,26 @@ relativesrcdir  = accessible/tree
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_button.xul \
 		test_colorpicker.xul \
 		test_combobox.xul \
 		test_filectrl.html \
+		test_formctrl.html \
+		test_formctrl.xul \
+		test_groupbox.xul \
+		test_iframe.html \
+		test_img.html \
+		test_list.html \
+		test_list_invalidate.html \
 		test_media.html \
 		test_menu.xul \
 		test_select.html \
+		test_table.html \
 		test_tree.xul \
+		test_txtcntr.html \
 		test_txtctrl.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/tree/test_formctrl.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>HTML form controls tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      // input@type="checkbox"
+      var accTree = {
+        role: ROLE_CHECKBUTTON,
+        children: [ ]
+      };
+
+      testAccessibleTree("checkbox", accTree);
+
+      // input@type="radio"
+      accTree = {
+        role: ROLE_RADIOBUTTON,
+        children: [ ]
+      };
+
+      testAccessibleTree("radio", accTree);
+
+      // input@type="button" and button
+      accTree = {
+        role: ROLE_PUSHBUTTON,
+        children: [ ]
+      };
+
+      testAccessibleTree("btn1", accTree);
+
+      // button
+      accTree = {
+        role: ROLE_PUSHBUTTON,
+        children: [
+          {
+            role: ROLE_TEXT_LEAF
+          }
+        ]
+      };
+
+      testAccessibleTree("btn2", accTree);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Fix O(n^2) access to all the children of a container"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045">
+    Mozilla Bug 342045
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <input type="checkbox" id="checkbox">
+  <input type="radio" id="radio">
+  <input type="button" value="button" id="btn1">
+  <button id="btn2">button</button>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_formctrl.xul
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible XUL checkbox and radio hierarchy tests">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    function doTest()
+    {
+      // checkbox
+      var accTree = {
+        role: ROLE_CHECKBUTTON,
+        children: [ ]
+      };
+
+      testAccessibleTree("checkbox", accTree);
+
+      // radiogroup
+      accTree = {
+        role: ROLE_GROUPING,
+        children: [
+          {
+            role: ROLE_RADIOBUTTON,
+            children: [ ]
+          },
+          {
+            role: ROLE_RADIOBUTTON,
+            children: [ ]
+          }
+        ]
+      };
+
+      testAccessibleTree("radiogroup", accTree);
+
+      SimpleTest.finish()
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045"
+         title="Fix O(n^2) access to all the children of a container">
+        Mozilla Bug 342045
+      </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <checkbox id="checkbox" label="checkbox"/>
+      <radiogroup id="radiogroup">
+        <radio label="radio1"/>
+        <radio label="radio2"/>
+      </radiogroup>
+    </vbox>
+  </hbox>
+
+</window>
+
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_groupbox.xul
@@ -0,0 +1,73 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible XUL groupbox hierarchy tests">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    function doTest()
+    {
+      accTree = {
+        role: ROLE_GROUPING,
+        children: [
+          {
+            role: ROLE_LABEL,
+            children: [ ]
+          },
+          {
+            role: ROLE_CHECKBUTTON,
+            children: [ ]
+          }
+        ]
+      };
+
+      testAccessibleTree("groupbox", accTree);
+
+      SimpleTest.finish()
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045"
+         title="Fix O(n^2) access to all the children of a container">
+        Mozilla Bug 342045
+      </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <groupbox id="groupbox">
+        <caption label="Some caption" />
+        <checkbox label="some checkbox label" />
+    </groupbox>
+    </vbox>
+  </hbox>
+
+</window>
+
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_iframe.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Outer document accessible tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var accTree = {
+        role: ROLE_INTERNAL_FRAME,
+        children: [
+          {
+            role: ROLE_DOCUMENT
+          }
+        ]
+      };
+
+      testAccessibleTree("iframe", accTree);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Fix O(n^2) access to all the children of a container"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045">
+    Mozilla Bug 342045
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <iframe id="iframe" src="about:mozilla">
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_img.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>HTML img tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      // image map
+      var accTree = {
+        role: ROLE_IMAGE_MAP,
+        children: [
+          {
+            role: ROLE_LINK,
+            children: []
+          },
+          {
+            role: ROLE_LINK,
+            children: []
+          }
+        ]
+      };
+
+      testAccessibleTree("imgmap", accTree);
+
+      // img
+      accTree = {
+        role: ROLE_GRAPHIC,
+        children: []
+      };
+
+      testAccessibleTree("img", accTree);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Fix O(n^2) access to all the children of a container"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045">
+    Mozilla Bug 342045
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <map name="atoz_map">
+    <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
+          coords="17,0,30,14" alt="b" shape="rect">
+    <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
+          coords="0,0,13,14" alt="a" shape="rect">
+  </map>
+
+  <img id="imgmap" width="447" height="15"
+       usemap="#atoz_map"
+       src="chrome://mochikit/content/a11y/accessible/letters.gif">
+
+  <img id="img" src="chrome://mochikit/content/a11y/accessible/moz.png">
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_list.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>HTML ul/li element tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function listItemTree(aBulletText, aName, aSubtree)
+    {
+      var obj = {
+        role: ROLE_LISTITEM,
+        children: [
+          {
+            role: ROLE_STATICTEXT,
+            name: aBulletText
+          },
+          {
+            role: ROLE_TEXT_LEAF,
+            name: aName
+          }
+        ]
+      };
+
+      if (aSubtree)
+        obj.children.push(aSubtree);
+
+      return obj;
+    }
+
+    function doTest()
+    {
+      var bulletText = String.fromCharCode(0x2022) + " ";
+
+      // list1
+      var accTree = {
+        role: ROLE_LIST,
+        children: [
+          new listItemTree(bulletText, "Oranges"),
+          new listItemTree(bulletText, "Apples"),
+          new listItemTree(bulletText, "Bananas")
+        ]
+      };
+
+      testAccessibleTree("list1", accTree);
+
+      // list2
+      accTree = {
+        role: ROLE_LIST,
+        children: [
+          new listItemTree("1. ", "Oranges"),
+          new listItemTree("2. ", "Apples"),
+          new listItemTree("3. ", "Bananas", accTree)
+        ]
+      };
+
+      testAccessibleTree("list2", accTree);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Fix O(n^2) access to all the children of a container"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045">
+    Mozilla Bug 342045
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <ul id="list1">
+    <li id="li1">Oranges</li>
+    <li id="li2">Apples</li>
+    <li id="li3">Bananas</li>
+  </ul>
+
+  <ol id="list2">
+    <li id="li4">Oranges</li>
+    <li id="li5">Apples</li>
+    <li id="li6">Bananas<ul>
+        <li id="n_li4">Oranges</li>
+        <li id="n_li5">Apples</li>
+        <li id="n_li6">Bananas</li>
+      </ul>
+    </li>
+  </ol>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_list_invalidate.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>Test HTML li and listitem bullet accessible cache</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Helpers
+
+    function testLiAccessibleTree()
+    {
+      // Test accessible tree.
+      var accTree = {
+        role: ROLE_LISTITEM,
+        children: [
+          {
+            role: ROLE_STATICTEXT,
+            children: []
+          },
+          {
+            role: ROLE_TEXT_LEAF,
+            children: []
+          }
+        ]
+      };
+
+      testAccessibleTree("li", accTree);
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Sequence item processors
+
+    function hideProcessor()
+    {
+      this.liNode = getNode("li");
+      this.li = getAccessible(this.liNode);
+      this.bullet = this.li.firstChild;
+
+      this.process = function hideProcessor_process()
+      {
+        this.liNode.style.display = "none";
+      }
+
+      this.onProcessed = function hideProcessor_onProcessed()
+      {
+        window.setTimeout(
+          function(aLiAcc, aLiNode, aBulletAcc)
+          {
+            testDefunctAccessible(aLiAcc, aLiNode);
+            testDefunctAccessible(aBulletAcc);
+
+            gSequence.processNext();
+          },
+          0, this.li, this.liNode, this.bullet
+        );
+      }
+    };
+
+    function showProcessor()
+    {
+      this.liNode = getNode("li");
+
+      this.process = function showProcessor_process()
+      {
+        this.liNode.style.display = "list-item";
+      }
+
+      this.onProcessed = function showProcessor_onProcessed()
+      {
+        testLiAccessibleTree();
+        SimpleTest.finish();
+      }
+    };
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    var gSequence = null;
+
+    function doTest()
+    {
+      testLiAccessibleTree();
+
+      gSequence = new sequence();
+
+      gSequence.append(new hideProcessor(), EVENT_HIDE, getAccessible("li"),
+                       "hide HTML li");
+      gSequence.append(new showProcessor(), EVENT_SHOW, getNode("li"),
+                       "show HTML li");
+
+      gSequence.processNext(); // SimpleTest.finish() will be called in the end
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="setParent shouldn't be virtual"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=496783">Mozilla Bug 496783</a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <ul>
+    <li id="li">item1</li>
+  </ul>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_table.html
@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>HTML table tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      //////////////////////////////////////////////////////////////////////////
+      // table1
+
+      var accTree = {
+        role: ROLE_TABLE,
+        children: [
+          {
+            role: ROLE_CAPTION,
+            children: [
+              {
+                role: ROLE_TEXT_LEAF
+              }
+            ]
+          },
+          {
+            role: ROLE_ROW,
+            children: [
+              {
+                role: ROLE_COLUMNHEADER
+              },
+              {
+                role: ROLE_COLUMNHEADER
+              }
+            ]
+          },
+          {
+            role: ROLE_ROW,
+            children: [
+              {
+                role: ROLE_CELL
+              },
+              {
+                role: ROLE_CELL
+              }
+            ]
+          },
+          {
+            role: ROLE_ROW,
+            children: [
+              {
+                role: ROLE_CELL
+              },
+              {
+                role: ROLE_CELL
+              }
+            ]
+          },
+          {
+            role: ROLE_ROW,
+            children: [
+              {
+                role: ROLE_CELL
+              },
+              {
+                role: ROLE_CELL
+              }
+            ]
+          }
+        ]
+      };
+
+      testAccessibleTree("table", accTree);
+
+      //////////////////////////////////////////////////////////////////////////
+      // table2 (consist of one column)
+
+      accTree = {
+        role: ROLE_TABLE,
+        children: [
+          {
+            role: ROLE_ROW,
+            children: [
+              {
+                role: ROLE_COLUMNHEADER
+              }
+            ]
+          },
+          {
+            role: ROLE_ROW,
+            children: [
+              {
+                role: ROLE_CELL
+              }
+            ]
+          }
+        ]
+      };
+
+      testAccessibleTree("table2", accTree);
+
+      //////////////////////////////////////////////////////////////////////////
+      // table3 (consist of one row)
+
+      accTree = {
+        role: ROLE_TABLE,
+        children: [
+          {
+            role: ROLE_ROW,
+            children: [
+              {
+                role: ROLE_ROWHEADER
+              },
+              {
+                role: ROLE_CELL
+              }
+            ]
+          }
+        ]
+      };
+
+      testAccessibleTree("table3", accTree);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="When a table has only one column per row and that column happens to be a column header its role is exposed wrong"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=529621">
+    Mozilla Bug 529621
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <table id="table">
+    <thead>
+      <tr>
+        <th>col1</th><th>col2</th>
+      </tr>
+    </thead>
+    <caption>caption</caption>
+    <tbody>
+      <tr>
+        <td>cell1</td><td>cell2</td>
+      </tr>
+    </tbody>
+    <tr>
+      <td>cell3</td><td>cell4</td>
+    </tr>
+    <caption>caption2</caption>
+    <tfoot>
+      <tr>
+        <td>cell5</td><td>cell6</td>
+      </tr>
+    </tfoot>
+  </table>
+
+  <table id="table2">
+    <thead>
+      <tr>
+        <th>colheader</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>bla</td>
+      </tr>
+    </tbody>
+  </table>
+
+  <table id="table3">
+    <tr>
+      <th>rowheader</th>
+      <td>cell</td>
+    </tr>
+  </table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_txtcntr.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>HTML text containers tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var accTree = {
+        role: ROLE_SECTION,
+        children: [
+          { // text child
+            role: ROLE_TEXT_LEAF,
+            children: []
+          }
+        ]
+      };
+
+      testAccessibleTree("c1", accTree);
+      testAccessibleTree("c2", accTree);
+
+      accTree = {
+        role: ROLE_SECTION,
+        children: [
+          {
+            role: ROLE_TEXT_LEAF,
+            name: "Hello1"
+          },
+          {
+            role: ROLE_WHITESPACE
+          },
+          {
+            role: ROLE_TEXT_LEAF,
+            name: "Hello2"
+          },
+          {
+            role: ROLE_SEPARATOR
+          },
+          {
+            role: ROLE_TEXT_LEAF,
+            name: "Hello3 "
+          },
+          {
+            role: ROLE_PARAGRAPH,
+            children: [
+              {
+                role: ROLE_TEXT_LEAF,
+                name: "Hello4 "
+              }
+            ]
+          }
+        ]
+      };
+
+      testAccessibleTree("c3", accTree);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="overflowed content doesn't expose child text accessibles"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=489306">Mozilla Bug 489306</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="c1" style="width: 100px; height: 100px; overflow: auto;">
+    1hellohello 2hellohello 3hellohello 4hellohello 5hellohello 6hellohello 7hellohello
+  </div>
+  <div id="c2">
+    1hellohello 2hellohello 3hellohello 4hellohello 5hellohello 6hellohello 7hellohello
+  </div>
+  <div id="c3">
+    Hello1<br>
+    Hello2<hr>
+    Hello3
+    <p>
+      Hello4
+    </p>
+  </div>
+</body>
+</html>
--- a/accessible/tests/mochitest/tree/test_txtctrl.html
+++ b/accessible/tests/mochitest/tree/test_txtctrl.html
@@ -1,39 +1,81 @@
 <!DOCTYPE html>
 <html>
 
 <head>
-  <title>HTML text containers tests</title>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <title>HTML text controls tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="chrome://mochikit/content/a11y/accessible/common.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/a11y/accessible/role.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
+      // editable div
       var accTree = {
         role: ROLE_SECTION,
         children: [
           { // text child
-            role: ROLE_TEXT_LEAF
+            role: ROLE_TEXT_LEAF,
+            children: []
+          }
+        ]
+      };
+
+      testAccessibleTree("txc1", accTree);
+
+      // input@type="text"
+      accTree = {
+        role: ROLE_ENTRY,
+        children: [
+          { // text child
+            role: ROLE_TEXT_LEAF,
+            children: []
           }
         ]
       };
 
-      testAccessibleTree("c1", accTree);
-      testAccessibleTree("c2", accTree);
+      testAccessibleTree("txc2", accTree);
+
+      // textarea
+      accTree = {
+        role: ROLE_ENTRY,
+        children: [
+          {
+            role: ROLE_TEXT_LEAF // hello1 text
+          },
+          {
+            role: ROLE_WHITESPACE
+          },
+          {
+            role: ROLE_TEXT_LEAF, // hello2 text
+          },
+          {
+            role: ROLE_WHITESPACE
+          },
+          {
+            role: ROLE_TEXT_LEAF, // whitepsace text
+          },
+          {
+            role: ROLE_WHITESPACE
+          }
+        ]
+      };
+
+      testAccessibleTree("txc3", accTree);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
@@ -42,16 +84,19 @@
   <a target="_blank"
      title="overflowed content doesn't expose child text accessibles"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=489306">Mozilla Bug 489306</a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
-  <div id="c1" style="width: 100px; height: 100px; overflow: auto;">
-    1hellohello 2hellohello 3hellohello 4hellohello 5hellohello 6hellohello 7hellohello
+  <div id="txc1" contentEditable="true">
+    1hellohello
   </div>
-  <div id="c2">
-    1hellohello 2hellohello 3hellohello 4hellohello 5hellohello 6hellohello 7hellohello
-  </div>
+  <input id="txc2" value="hello">
+  <textarea id="txc3">
+    hello1
+    hello2
+  </textarea>
+
 </body>
 </html>
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3393,17 +3393,17 @@
         tabcontainer.mTabstrip.addEventListener("scroll", this, false);
 
         for (var i = 0; i < tabs.length; i++) {
           this._createTabMenuItem(tabs[i]);
         }
         this._updateTabsVisibilityStatus();
       ]]></handler>
 
-      <handler event="popuphiding">
+      <handler event="popuphidden">
       <![CDATA[
         // clear out the menu popup and remove the listeners
         while (this.hasChildNodes()) {
           var menuItem = this.lastChild;
           menuItem.removeEventListener("command", this, false);
           menuItem.tab.removeEventListener("DOMAttrModified", this, false);
           menuItem.tab.removeEventListener("TabClose", this, false);
           menuItem.tab.mCorrespondingMenuitem = null;
--- a/browser/base/content/test/browser_drag.js
+++ b/browser/base/content/test/browser_drag.js
@@ -15,9 +15,12 @@ function test()
 
   // set the valid attribute so dropping is allowed
   var proxyicon = document.getElementById("page-proxy-favicon")
   var oldstate = proxyicon.getAttribute("pageproxystate");
   proxyicon.setAttribute("pageproxystate", "valid");
   var dt = EventUtils.synthesizeDragStart(proxyicon, expected);
   is(dt, null, "drag on proxy icon");
   proxyicon.setAttribute("pageproxystate", oldstate);
+  // Now, the identity information panel is opened by the proxy icon click.
+  // We need to close it for next tests.
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
 }
--- a/browser/base/content/test/browser_overflowScroll.js
+++ b/browser/base/content/test/browser_overflowScroll.js
@@ -11,16 +11,23 @@ function isLeft(ele, msg)    is(left(ele
 function isRight(ele, msg)   is(right(ele), right(scrollbox), msg);
 function elementFromPoint(x) tabstrip._elementFromPoint(x);
 function nextLeftElement()   elementFromPoint(left(scrollbox) - 1);
 function nextRightElement()  elementFromPoint(right(scrollbox) + 1);
 
 function test() {
   waitForExplicitFinish();
 
+  // If the previous (or more) test finished with cleaning up the tabs,
+  // there may be some pending animations. That can cause a failure of
+  // this tests, so, we should test this in another stack.
+  setTimeout(doTest, 0);
+}
+
+function doTest() {
   tabstrip.smoothScroll = false;
 
   var tabMinWidth = gPrefService.getIntPref("browser.tabs.tabMinWidth");
   var tabCountForOverflow = Math.ceil(width(tabstrip) / tabMinWidth * 3);
   while (tabContainer.childNodes.length < tabCountForOverflow)
     gBrowser.addTab();
 
   tabstrip.addEventListener("overflow", runOverflowTests, false);
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -48,17 +48,18 @@
 
   <binding id="places-popup-base"
            extends="chrome://global/content/bindings/popup.xml#popup">
     <content>
       <xul:hbox flex="1">
         <xul:vbox class="menupopup-drop-indicator-bar" hidden="true">
           <xul:image class="menupopup-drop-indicator" mousethrough="always"/>
         </xul:vbox>
-        <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical">
+        <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
+                            smoothscroll="false">
           <children/>
         </xul:arrowscrollbox>
       </xul:hbox>
     </content>
 
     <implementation>
 
       <field name="_indicatorBar">
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -582,24 +582,26 @@ SessionStoreService.prototype = {
    */
   onLoad: function sss_onLoad(aWindow) {
     // return if window has already been initialized
     if (aWindow && aWindow.__SSi && this._windows[aWindow.__SSi])
       return;
 
     // ignore non-browser windows and windows opened while shutting down
     if (aWindow.document.documentElement.getAttribute("windowtype") != "navigator:browser" ||
-      this._loadState == STATE_QUITTING)
+        this._loadState == STATE_QUITTING)
       return;
 
     // assign it a unique identifier (timestamp)
     aWindow.__SSi = "window" + Date.now();
 
     // and create its data object
     this._windows[aWindow.__SSi] = { tabs: [], selected: 0, _closedTabs: [] };
+    if (!this._isWindowLoaded(aWindow))
+      this._windows[aWindow.__SSi]._restoring = true;
     if (!aWindow.toolbar.visible)
       this._windows[aWindow.__SSi].isPopup = true;
     
     // perform additional initialization when the first window is loading
     if (this._loadState == STATE_STOPPED) {
       this._loadState = STATE_RUNNING;
       this._lastSaveTime = Date.now();
       
@@ -1737,16 +1739,18 @@ SessionStoreService.prototype = {
       this._dirtyWindows = [];
     }
     
     // collect the data for all windows
     var total = [], windows = [];
     var nonPopupCount = 0;
     var ix;
     for (ix in this._windows) {
+      if (this._windows[ix]._restoring) // window data is still in _statesToRestore
+        continue;
       total.push(this._windows[ix]);
       windows.push(ix);
       if (!this._windows[ix].isPopup)
         nonPopupCount++;
     }
     this._updateCookies(total);
 
     // collect the data for all windows yet to be restored
@@ -2028,16 +2032,17 @@ SessionStoreService.prototype = {
         tabbrowser.selectedTab = aTabs[0];
       }
     }
 
     if (!this._isWindowLoaded(aWindow)) {
       // from now on, the data will come from the actual window
       delete this._statesToRestore[aWindow.__SS_restoreID];
       delete aWindow.__SS_restoreID;
+      delete this._windows[aWindow.__SSi]._restoring;
     }
     
     // helper hash for ensuring unique frame IDs
     var idMap = { used: {} };
     this.restoreHistory(aWindow, aTabs, aTabData, idMap);
   },
 
   /**
--- a/browser/themes/pinstripe/browser/places/places.css
+++ b/browser/themes/pinstripe/browser/places/places.css
@@ -40,22 +40,22 @@
   border-top: @sidebarItemBorderTop@;
 }
 
 .sidebar-placesTreechildren::-moz-tree-row(selected,focus) {
   background: @sidebarItemFocusedBackground@;
   border-top: @sidebarItemFocusedBorderTop@;
 }
 
-.sidebar-placesTreechildren::-moz-tree-row(selected):-moz-system-metric(mac-graphite-theme) {
+.sidebar-placesTreechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected) {
   background: @sidebarItemGraphiteBackground@;
   border-top: @sidebarItemGraphiteBorderTop@;
 }
 
-.sidebar-placesTreechildren::-moz-tree-row(selected,focus):-moz-system-metric(mac-graphite-theme) {
+.sidebar-placesTreechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected,focus) {
   background: @sidebarItemGraphiteFocusedBackground@;
   border-top: @sidebarItemGraphiteFocusedBorderTop@;
 }
 
 .sidebar-placesTreechildren::-moz-tree-cell-text(selected) {  
   font-weight: bold !important;
   color: #ffffff !important;
 }
@@ -63,17 +63,17 @@
 #sidebar-search-label {
   display: none;
 }
 
 #viewButton {
   -moz-appearance: none;
   border: 1px solid #7F7F7F;
   -moz-border-radius: 10px;
-  background: url("chrome://global/skin/icons/white-gray-gradient.gif") #A09E9D repeat-x top center;
+  background: @toolbarbuttonBackground@;
   min-width: 0px;
   min-height: 0px;
   -moz-padding-start: 5px;
   -moz-padding-end: 0px;
   padding-top: 1px;
   padding-bottom: 1px;
 }
 
--- a/build/autoconf/config.sub
+++ b/build/autoconf/config.sub
@@ -1,15 +1,15 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 #   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
 #   Free Software Foundation, Inc.
 
-timestamp='2009-08-19'
+timestamp='2009-12-04'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
 # can handle that machine.  It does not imply ALL GNU software can.
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
@@ -121,17 +121,17 @@ esac
 
 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
   nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
   uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
   kopensolaris*-gnu* | \
-  storm-chaos* | os2-emx* | rtmk-nova*)
+  storm-chaos* | os2-emx* | rtmk-nova* | wince-winmo*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
   *)
     basic_machine=`echo $1 | sed 's/-[^-]*$//'`
     if [ $basic_machine != $1 ]
     then os=`echo $1 | sed 's/.*-/-/'`
     else os=; fi
@@ -1291,17 +1291,17 @@ case $os in
 	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -winmo*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
 		case $basic_machine in
 		    x86-* | i*86-*)
 			;;
 		    *)
 			os=-nto$os
@@ -1333,16 +1333,19 @@ case $os in
 		os=`echo $os | sed -e 's|sunos6|solaris3|'`
 		;;
 	-opened*)
 		os=-openedition
 		;;
         -os400*)
 		os=-os400
 		;;
+	-wince-winmo*)
+		os=-wince-winmo
+		;;
 	-wince*)
 		os=-wince
 		;;
 	-osfrose*)
 		os=-osfrose
 		;;
 	-osf*)
 		os=-osf
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -255,17 +255,16 @@ user_pref("javascript.options.showInCons
 user_pref("layout.debug.enable_data_xbl", true);
 user_pref("browser.EULA.override", true);
 user_pref("javascript.options.jit.content", true);
 user_pref("gfx.color_management.force_srgb", true);
 user_pref("network.manage-offline-status", false);
 user_pref("test.mousescroll", true);
 user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs
 user_pref("network.http.prompt-temp-redirect", false);
-user_pref("svg.smil.enabled", true); // Needed for SMIL mochitests until bug 482402 lands
 user_pref("media.cache_size", 100);
 user_pref("security.warn_viewing_mixed", false);
 
 user_pref("geo.wifi.uri", "http://localhost:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs");
 user_pref("geo.wifi.testing", true);
 
 user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
 
--- a/build/wince/tools/Makefile
+++ b/build/wince/tools/Makefile
@@ -89,21 +89,21 @@ endif
 
 ifdef VPATH
 CFLAGS	+= -DSHUNT_INC='"$(OBJDIR)/dist/include/mozce_shunt"'
 CFLAGS	+= -DSHUNT_LIB='"$(OBJDIR)/dist/lib"'
 CFLAGS	+= -DJEMALLOC_LIB='"$(OBJDIR)/dist/lib/jemalloc.lib"'
 endif
 CFLAGS += -DEBUG -Zi
 
-SDK_TOOLS = $(MOZCE_TOOLS_BIN_DIR)/arm-wince-as.exe \
-            $(MOZCE_TOOLS_BIN_DIR)/arm-wince-gcc.exe \
-            $(MOZCE_TOOLS_BIN_DIR)/arm-wince-lib.exe \
-            $(MOZCE_TOOLS_BIN_DIR)/arm-wince-link.exe \
-            $(MOZCE_TOOLS_BIN_DIR)/arm-wince-res.exe 
+SDK_TOOLS = $(MOZCE_TOOLS_BIN_DIR)/$(target)-as.exe \
+            $(MOZCE_TOOLS_BIN_DIR)/$(target)-gcc.exe \
+            $(MOZCE_TOOLS_BIN_DIR)/$(target)-lib.exe \
+            $(MOZCE_TOOLS_BIN_DIR)/$(target)-link.exe \
+            $(MOZCE_TOOLS_BIN_DIR)/$(target)-res.exe 
 
 all: libs export
 
 libs: $(SDK_TOOLS)
 
 clean: clobber
 
 
@@ -113,33 +113,33 @@ clobber:
 $(MOZCE_TOOLS_BIN_DIR)/linkargs.obj:	$(MOZCE_TOOLS_DIR)/linkargs.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile
 	mkdir -p $(MOZCE_TOOLS_BIN_DIR);
 	$(CC) $(CFLAGS) -c -Fo$(MOZCE_TOOLS_BIN_DIR)/linkargs.obj $(MOZCE_TOOLS_DIR)/linkargs.c
 
 $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj:	$(MOZCE_TOOLS_DIR)/toolspath.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile
 	mkdir -p $(MOZCE_TOOLS_BIN_DIR);
 	$(CC) $(CFLAGS) -c -Fo$(MOZCE_TOOLS_BIN_DIR)/toolspath.obj $(MOZCE_TOOLS_DIR)/toolspath.c
 
-$(MOZCE_TOOLS_BIN_DIR)/arm-wince-as.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-as.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
+$(MOZCE_TOOLS_BIN_DIR)/$(target)-as.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-as.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 	mkdir -p $(MOZCE_TOOLS_BIN_DIR);
 	$(CC) $(CFLAGS) -Fo$(MOZCE_TOOLS_BIN_DIR) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-as.c -link $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 
-$(MOZCE_TOOLS_BIN_DIR)/arm-wince-gcc.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-gcc.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/linkargs.obj $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
+$(MOZCE_TOOLS_BIN_DIR)/$(target)-gcc.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-gcc.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/linkargs.obj $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 	mkdir -p $(MOZCE_TOOLS_BIN_DIR);
 	$(CC) $(CFLAGS) -Fo$(MOZCE_TOOLS_BIN_DIR) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-gcc.c -link $(MOZCE_TOOLS_BIN_DIR)/linkargs.obj $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 
-$(MOZCE_TOOLS_BIN_DIR)/arm-wince-lib.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-lib.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
+$(MOZCE_TOOLS_BIN_DIR)/$(target)-lib.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-lib.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 	mkdir -p $(MOZCE_TOOLS_BIN_DIR);
 	$(CC) $(CFLAGS) -Fo$(MOZCE_TOOLS_BIN_DIR) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-lib.c -link $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 
-$(MOZCE_TOOLS_BIN_DIR)/arm-wince-link.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-link.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/linkargs.obj $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
+$(MOZCE_TOOLS_BIN_DIR)/$(target)-link.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-link.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/linkargs.obj $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 	mkdir -p $(MOZCE_TOOLS_BIN_DIR);
 	$(CC) $(CFLAGS) -Fo$(MOZCE_TOOLS_BIN_DIR) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-link.c -link $(MOZCE_TOOLS_BIN_DIR)/linkargs.obj $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 
-$(MOZCE_TOOLS_BIN_DIR)/arm-wince-res.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-res.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
+$(MOZCE_TOOLS_BIN_DIR)/$(target)-res.exe:	$(MOZCE_TOOLS_DIR)/arm-wince-res.c $(MOZCE_TOOLS_DIR)/toolspath.h $(MOZCE_TOOLS_DIR)/Makefile $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 	mkdir -p $(MOZCE_TOOLS_BIN_DIR);
 	$(CC) $(CFLAGS) -Fo$(MOZCE_TOOLS_BIN_DIR) -Fe$@ $(MOZCE_TOOLS_DIR)/arm-wince-res.c -link $(MOZCE_TOOLS_BIN_DIR)/toolspath.obj
 
 
 export:: $(SDK_TOOLS)
 ifdef MOZCE_NOT_CONFIGURE
 	mkdir -p $(OBJDIR)/dist/sdk/bin
 	cp $^ $(OBJDIR)/dist/sdk/bin
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -694,17 +694,17 @@ ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 OUTOPTION = -Fo# eol
 else
 OUTOPTION = -o # eol
 endif # WINNT && !GNU_CC
 ifneq (,$(filter WINCE,$(OS_ARCH)))
 OUTOPTION = -Fo# eol
 endif
 
-ifeq ($(OS_TARGET), WINCE)
+ifeq ($(OS_ARCH), WINCE)
 OUTOPTION = -Fo# eol
 HOST_OUTOPTION = -Fo# eol
 else
 
 ifeq (,$(CROSS_COMPILE))
 HOST_OUTOPTION = $(OUTOPTION)
 else
 HOST_OUTOPTION = -o # eol
--- a/configure.in
+++ b/configure.in
@@ -247,64 +247,53 @@ dnl ====================================
 dnl Set CROSS_COMPILE in the environment when running configure
 dnl to use the cross-compile setup for now
 dnl ========================================================
 
 if test "$COMPILE_ENVIRONMENT"; then
 
 dnl Do some special WinCE toolchain stuff
 case "$target" in
-*wince)
+*wince|*winmo)
 
     MOZ_ARG_WITH_STRING(wince-sdk,
     [  --with-wince-sdk=WINCE_SDK_DIR
                         The path to the Windows CE SDK],
     WINCE_SDK_DIR=$withval)
 
     MOZ_ARG_WITH_STRING(ogles-sdk,
     [  --with-ogles-sdk=OGLES_SDK_DIR
                         The path to the OGLES SDK],
     OGLES_SDK_DIR=$withval)
 
-    dnl Default to Windows Mobile components enabled
-    WINCE_WINDOWS_MOBILE=1
-
-    MOZ_ARG_DISABLE_BOOL(windows-mobile-components,
-    [  --disable-windows-mobile-components
-         Disable Windows Mobile specific components from CE build],
-    WINCE_WINDOWS_MOBILE=,
-    WINCE_WINDOWS_MOBILE=1)
-
-    if test "$WINCE_WINDOWS_MOBILE"; then
-        AC_DEFINE(WINCE_WINDOWS_MOBILE)
-    fi
-
     AC_DEFINE(WINCE)
     
     export WINCE=1
 
     echo -----------------------------------------------------------------------------
     echo Building Windows CE Shunt Library and Tool Chain
     echo Using SDK in:
     echo $WINCE_SDK_DIR
 
     ac_exeext=.exe
 
     _pwd=`pwd -W`
     _topsrcdirwin=`cd \`dirname $0\`; pwd -W`
-    make OGLES_SDK_DIR="$OGLES_SDK_DIR" WINCE_SDK_DIR="$WINCE_SDK_DIR" TOPSRCDIR="$_topsrcdirwin" OBJDIR="$_pwd" -C $srcdir/build/wince/tools
-
-    CC="$_pwd/dist/sdk/bin/arm-wince-gcc.exe"
-    CXX="$_pwd/dist/sdk/bin/arm-wince-gcc.exe"
-    CPP="$_pwd/dist/sdk/bin/arm-wince-gcc.exe -E -nologo"
-    CXXCPP="$_pwd/dist/sdk/bin/arm-wince-gcc.exe -TP -E -nologo"
-    LD="$_pwd/dist/sdk/bin/arm-wince-link.exe"
-    AR="$_pwd/dist/sdk/bin/arm-wince-lib.exe"
-    AS="$_pwd/dist/sdk/bin/arm-wince-as.exe"
-    RC="$_pwd/dist/sdk/bin/arm-wince-res.exe"
+    make OGLES_SDK_DIR="$OGLES_SDK_DIR" WINCE_SDK_DIR="$WINCE_SDK_DIR" \
+    TOPSRCDIR="$_topsrcdirwin" OBJDIR="$_pwd" target="$target" \
+    -C $srcdir/build/wince/tools
+
+    CC="$_pwd/dist/sdk/bin/$target-gcc.exe"
+    CXX="$_pwd/dist/sdk/bin/$target-gcc.exe"
+    CPP="$_pwd/dist/sdk/bin/$target-gcc.exe -E -nologo"
+    CXXCPP="$_pwd/dist/sdk/bin/$target-gcc.exe -TP -E -nologo"
+    LD="$_pwd/dist/sdk/bin/$target-link.exe"
+    AR="$_pwd/dist/sdk/bin/$target-lib.exe"
+    AS="$_pwd/dist/sdk/bin/$target-as.exe"
+    RC="$_pwd/dist/sdk/bin/$target-res.exe"
 
 
     echo -----------------------------------------------------------------------------
 
     ;;
 esac
 
 if test -n "$CROSS_COMPILE" && test "$target" != "$host"; then
@@ -468,17 +457,17 @@ if test "$GXX" = yes; then
    if test "`$CXX -help 2>&1 | grep -c 'Intel(R) C++ Compiler'`" != "0"; then
      INTEL_CXX=1
    fi
 fi
 
 dnl Special win32 checks
 dnl ========================================================
 case "$target" in
-*-wince)
+*-wince|*-winmo)
     WINVER=500
     ;;
 *)
     WINVER=502
     ;;
 esac
 
 dnl Target the Windows 7 SDK by default
@@ -521,17 +510,17 @@ if test "$MOZ_WINSDK_TARGETVER" -lt "060
     # We can't build parental controls either
     MOZ_DISABLE_PARENTAL_CONTROLS=1
 fi
 fi
 
 AC_SUBST(MOZ_DISABLE_VISTA_SDK_REQUIREMENTS)
 
 case "$target" in
-*-cygwin*|*-mingw*|*-msvc*|*-mks*|*-wince)
+*-cygwin*|*-mingw*|*-msvc*|*-mks*|*-wince|*-winmo)
     if test "$GCC" != "yes"; then
         # Check to see if we are really running in a msvc environemnt
         _WIN32_MSVC=1
         AC_CHECK_PROGS(MIDL, midl)
 
         # Make sure compilers are valid
         CFLAGS="$CFLAGS -TC -nologo"
         CXXFLAGS="$CXXFLAGS -TP -nologo"
@@ -776,17 +765,17 @@ AC_PROG_CXXCPP
 if test -n "$_WIN32_MSVC"; then
     SKIP_PATH_CHECKS=1
     SKIP_COMPILER_CHECKS=1
     SKIP_LIBRARY_CHECKS=1
 
     # Since we're skipping compiler and library checks, hard-code
     # some facts here.
     case "$target" in
-    *-wince)
+    *-wince|*-winmo)
         ;;
     *)
         AC_DEFINE(HAVE_IO_H)
         AC_DEFINE(HAVE_SETBUF)
         AC_DEFINE(HAVE_ISATTY)
         ;;
     esac
 fi
@@ -1087,16 +1076,17 @@ if test -n "$CROSS_COMPILE"; then
     OS_ARCH=`echo $target_os | sed -e 's|/|_|g'`
     OS_RELEASE=
     case "${target_os}" in
         linux*)       OS_ARCH=Linux OS_TARGET=Linux ;;
         kfreebsd*-gnu) OS_ARCH=GNU_kFreeBSD OS_TARGET=GNU_kFreeBSD ;;
         solaris*)     OS_ARCH=SunOS OS_RELEASE=5 ;;
         mingw*)       OS_ARCH=WINNT ;;
         wince*)       OS_ARCH=WINCE ;;
+        winmo*)       OS_ARCH=WINCE ;;
         darwin*)      OS_ARCH=Darwin OS_TARGET=Darwin ;;
     esac
 else
     OS_TARGET=`uname -s`
     OS_ARCH=`uname -s | sed -e 's|/|_|g'`
     OS_RELEASE=`uname -r`
 fi
 
@@ -1297,17 +1287,26 @@ SINIX-N | SINIX-Y | SINIX-Z |ReliantUNIX
     OS_TEST=`uname -p`
     ;;
 UnixWare)
     OS_ARCH=UNIXWARE
     OS_RELEASE=`uname -v`
     ;;
 WINCE)
     OS_ARCH=WINCE
-    OS_TARGET=WINCE
+    case "${target_os}" in
+    *winmo)
+        OS_TARGET=WINMO
+        WINCE_WINDOWS_MOBILE=1
+        AC_DEFINE(WINCE_WINDOWS_MOBILE)
+        ;;
+    *)
+        OS_TARGET=WINCE
+        ;;
+    esac
     ;;
 Darwin)
     case "${target_cpu}" in
     powerpc*)
         OS_TEST=ppc
         ;;
     i*86*)
         OS_TEST=i386 
@@ -1645,17 +1644,17 @@ dnl System overrides of the defaults for
 dnl ========================================================
 case "$host" in
 *-beos*)
     HOST_CFLAGS="$HOST_CFLAGS -DXP_BEOS -DBeOS -DBEOS -D_POSIX_SOURCE -DNO_X11"
     HOST_NSPR_MDCPUCFG='\"md/_beos.cfg\"'
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
     ;;
 
-*cygwin*|*mingw*|*mks*|*msvc*|*wince)
+*cygwin*|*mingw*|*mks*|*msvc*|*wince|*winmo)
     # we need Python 2.5 on Windows
     PYTHON_VERSION=2.5
     if test -n "$_WIN32_MSVC"; then
         HOST_AR=lib
         HOST_AR_FLAGS='-NOLOGO -OUT:"$@"'
         HOST_CFLAGS="$HOST_CFLAGS -TC -nologo -Fd\$(HOST_PDBFILE)"
         HOST_RANLIB='echo ranlib'
     else
@@ -2016,17 +2015,17 @@ case "$target" in
     	USE_ELF_DYNSTR_GC=1
     ;;
     mips*)
         MOZ_DEBUG_FLAGS="-g" # We want inlining
     ;;
     esac
     ;;
 
-*-wince*)
+*-wince*|*-winmo*)
     TARGET_COMPILER_ABI=msvc
     _PLATFORM_DEFAULT_TOOLKIT=cairo-windows
     _PLATFORM_MOZ_DISABLE_VISTA_SDK_REQUIREMENTS=1
     MOZ_TOOLS_DIR=`cd $MOZ_TOOLS && pwd -W`
     MOZ_BUILD_ROOT=`cd $MOZ_BUILD_ROOT && pwd -W`
     AR_LIST="$AR -list"
     AR_EXTRACT="$AR -extract"
     AR_DELETE="$AR d"
@@ -2710,17 +2709,17 @@ case "$target" in
     NO_LD_ARCHIVE_FLAGS=
     ;;
 *-aix4.3*|*-aix5*)
     NO_LD_ARCHIVE_FLAGS=
     ;;
 *-openvms*)
     NO_LD_ARCHIVE_FLAGS=
     ;;
-*-msvc*|*-mks*|*-mingw*|*-cygwin*|*-wince)
+*-msvc*|*-mks*|*-mingw*|*-cygwin*|*-wince|*-winmo)
     if test -z "$GNU_CC"; then
         NO_LD_ARCHIVE_FLAGS=
     fi
     ;;
 esac
 AC_SUBST(NO_LD_ARCHIVE_FLAGS)
 
 dnl ========================================================
@@ -2742,17 +2741,17 @@ case "$target" in
         fi
         ;;
     *-nto*) 
         MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script'
         ;;
     *-darwin*)
         MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,-exported_symbols_list -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-export-list'
         ;;
-    *-cygwin*|*-mingw*|*-mks*|*-msvc|*-wince)
+    *-cygwin*|*-mingw*|*-mks*|*-msvc|*-wince|*-winmo)
         if test -n "$GNU_CC"; then
            MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script'
         fi
         ;;
 esac
 
 if test -z "$COMPILE_ENVIRONMENT"; then
     SKIP_COMPILER_CHECKS=1
@@ -3637,17 +3636,17 @@ AC_CACHE_CHECK(
         )]
     )
 
 if test "$ac_cv_func_gnu_get_libc_version" = "yes"; then
     AC_DEFINE(HAVE_GNU_GET_LIBC_VERSION)
 fi
 
 case $target_os in
-    os2*|msvc*|mks*|cygwin*|mingw*|darwin*|wince*|beos*)
+    os2*|msvc*|mks*|cygwin*|mingw*|darwin*|wince*|winmo*|beos*)
         ;;
     *)
     
 AC_CHECK_LIB(c, iconv, [_ICONV_LIBS="$_ICONV_LIBS"],
     AC_CHECK_LIB(iconv, iconv, [_ICONV_LIBS="$_ICONV_LIBS -liconv"],
         AC_CHECK_LIB(iconv, libiconv, [_ICONV_LIBS="$_ICONV_LIBS -liconv"])))
 _SAVE_LIBS=$LIBS
 LIBS="$LIBS $_ICONV_LIBS"
@@ -4772,40 +4771,39 @@ dnl ====================================
 case "$MOZ_WIDGET_TOOLKIT" in
 photon)
 	MOZ_ENABLE_PHOTON=1
 	AC_DEFINE(MOZ_WIDGET_PHOTON)
     ;;
 
 cairo-windows)
     MOZ_WIDGET_TOOLKIT=windows
-    if test -z "$WINCE"; then
-        MOZ_WEBGL=1
-    fi
+    MOZ_WEBGL=1
     ;;
 
 cairo-gtk2|cairo-gtk2-x11)
     MOZ_WIDGET_TOOLKIT=gtk2
     MOZ_ENABLE_GTK2=1
     MOZ_ENABLE_XREMOTE=1
     MOZ_WEBGL=1
+    MOZ_WEBGL_GLX=1
 
     AC_DEFINE(MOZ_X11)
     MOZ_X11=1
     USE_FC_FREETYPE=1
 
     TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
     TK_LIBS='$(MOZ_GTK2_LIBS)'
     AC_DEFINE(MOZ_WIDGET_GTK2)
     ;;
 
 cairo-gtk2-dfb)
     MOZ_WIDGET_TOOLKIT=gtk2
     MOZ_ENABLE_GTK2=1
-    MOZ_WEBGL=1
+    MOZ_WEBGL=
 
     AC_DEFINE(MOZ_DFB)
     MOZ_DFB=1
 
     TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
     TK_LIBS='$(MOZ_GTK2_LIBS)'
     AC_DEFINE(MOZ_WIDGET_GTK2)
     if test "$no_x" != "yes"; then
@@ -5951,17 +5949,17 @@ if test -n "$MOZ_TREE_FREETYPE"; then
    AC_SUBST(CAIRO_FT_CFLAGS)
 fi
 
 
 dnl ========================================================
 dnl Installer
 dnl ========================================================
 case "$target_os" in
-    aix*|solaris*|linux*|msvc*|mks*|cygwin*|mingw*|os2*|wince*)
+    aix*|solaris*|linux*|msvc*|mks*|cygwin*|mingw*|os2*|wince*|winmo*)
         MOZ_INSTALLER=1
         ;;
 esac
 
 MOZ_ARG_DISABLE_BOOL(installer,
 [  --disable-installer     Disable building of installer],
     MOZ_INSTALLER=,
     MOZ_INSTALLER=1 )
@@ -6296,17 +6294,17 @@ PKG_CHECK_MODULES(LIBOSSO,libosso,
                   NS_OSSO=)
 
 if test $NS_OSSO; then
     if test -z "$MOZ_ENABLE_DBUS"; then
         AC_MSG_ERROR([DBus is required when building for OSSO])
     fi
     AC_DEFINE(NS_OSSO)
     MOZ_GFX_OPTIMIZE_MOBILE=1
-    MOZ_WEBGL=
+    MOZ_WEBGL_GLX=
 fi
 AC_SUBST(LIBOSSO_CFLAGS)
 AC_SUBST(LIBOSSO_LIBS)
 
 PKG_CHECK_MODULES(LIBHILDONFM,hildon-fm-2,
                   NS_HILDONFM=1,
                   NS_HILDONFM)
 AC_SUBST(LIBHILDONFM_CFLAGS)
@@ -6376,17 +6374,17 @@ MOZ_ARG_ENABLE_STRING(debug,
   fi ],
   MOZ_DEBUG=)
 
 MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG"
  case "${target_os}" in
     beos*)
         MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${USER}"
         ;;
-    msvc*|mks*|cygwin*|mingw*|os2*|wince*)
+    msvc*|mks*|cygwin*|mingw*|os2*|wince*|winmo*)
         MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_`echo ${USERNAME} | sed -e 's| |_|g'`"
         ;;
     *) 
         MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_`$WHOAMI`"
         ;;
   esac
 MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DTRACING"
 
@@ -6629,16 +6627,20 @@ if test "$MOZ_MEMORY"; then
     ;;
   *wince)
     AC_DEFINE(MOZ_MEMORY_WINCE)
     AC_DEFINE(MOZ_MEMORY_WINDOWS)
     if test -z "$WINCE_WINDOWS_MOBILE"; then
       AC_DEFINE(MOZ_MEMORY_WINCE6)
     fi
     ;;
+  *winmo)
+    AC_DEFINE(MOZ_MEMORY_WINCE)
+    AC_DEFINE(MOZ_MEMORY_WINDOWS)
+    ;;
   *)
     AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
     ;;
   esac
 fi
 AC_SUBST(MOZ_MEMORY)
 AC_SUBST(MOZ_MEMORY_LDFLAGS)
 AC_SUBST(WIN32_CRT_SRC_DIR)
@@ -7361,17 +7363,17 @@ dnl =
 dnl = Standalone module options
 dnl = 
 dnl ========================================================
 MOZ_ARG_HEADER(Standalone module options (Not for building Mozilla))
 
 dnl Check for GLib and libIDL.
 dnl ========================================================
 case "$target_os" in
-msvc*|mks*|cygwin*|mingw*|wince*)
+msvc*|mks*|cygwin*|mingw*|wince*|winmo*)
     SKIP_IDL_CHECK="yes"
     ;;
 *)
     SKIP_IDL_CHECK="no"
     ;;
 esac
 
 if test -z "$COMPILE_ENVIRONMENT"; then
@@ -7806,17 +7808,17 @@ AC_SUBST(NECKO_COOKIES)
 if test "$NECKO_COOKIES"; then
     AC_DEFINE(NECKO_COOKIES)
 fi
 
 dnl
 dnl Build jsctypes on the platforms we can.
 dnl
 AC_SUBST(BUILD_CTYPES)
-if test "$OS_TARGET" != "WINCE" -o `echo $OS_TEST | grep -ic arm` != 1; then
+if test "$OS_ARCH" != "WINCE" -o `echo $OS_TEST | grep -ic arm` != 1; then
   BUILD_CTYPES=1
   AC_DEFINE(BUILD_CTYPES)
 fi
 
 dnl NECKO_ configuration options are not global
 _NON_GLOBAL_ACDEFINES="$_NON_GLOBAL_ACDEFINES NECKO_"
 
 dnl Only build Mork if it's required
@@ -8136,24 +8138,22 @@ if test "$MOZ_X11"; then
 
     if test ! -z "$MISSING_X"; then
         AC_MSG_ERROR([ Could not find the following X libraries: $MISSING_X ]);
     fi
 
 fi # MOZ_X11
 
 dnl Check for headers, etc. needed by WebGL.
-if test -n "$MOZ_WEBGL"; then
-    if test "$MOZ_WIDGET_TOOLKIT" = gtk2; then
-        AC_CHECK_HEADER(GL/glx.h)
-        if test "$ac_cv_header_GL_glx_h" != "yes"; then
-            AC_MSG_ERROR([Can't find header GL/glx.h for WebGL (install mesa-common-dev (Ubuntu), mesa-libGL-devel (Fedora), or Mesa (SuSE))])
-        fi
-    fi
-fi # MOZ_WEBGL
+if test -n "$MOZ_WEBGL_GLX"; then
+    AC_CHECK_HEADER(GL/glx.h)
+    if test "$ac_cv_header_GL_glx_h" != "yes"; then
+        AC_MSG_ERROR([Can't find header GL/glx.h for WebGL (install mesa-common-dev (Ubuntu), mesa-libGL-devel (Fedora), or Mesa (SuSE))])
+    fi
+fi # MOZ_WEBGL_GLX
 fi # COMPILE_ENVIRONMENT
 
 if test "$USE_FC_FREETYPE"; then
     if test "$COMPILE_ENVIRONMENT"; then
     	_SAVE_CPPFLAGS="$CPPFLAGS"
     	CPPFLAGS="$CPPFLAGS $FT2_CFLAGS $XCFLAGS"
         AC_CHECK_HEADERS(fontconfig/fcfreetype.h, , 
             [AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)])
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/450383-1.html
@@ -0,0 +1,9 @@
+<html>
+<BODY></BODY>
+<SCRIPT>
+    document.addEventListener("DOMCharacterDataModified",function(){
+        document.body.innerHTML=""; // change this to see memory corruption
+    },true);
+    document.body.innerHTML="<optGroup</form<textArea";
+</SCRIPT>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/450385-1.html
@@ -0,0 +1,11 @@
+<html>
+<BODY></BODY>
+<SCRIPT>
+document.body.addEventListener("DOMCharacterDataModified", function () {
+    document.body.innerHTML = "";
+    eventChild.appendChild(event.relatedNode);
+}, true);
+document.addEventListener("DOMNodeInserted", function () {}, true);
+document.body.innerHTML="]<kbd><small></kbd><base><optGroup></optGroup>";
+</SCRIPT>
+</html>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -43,16 +43,18 @@ load 401993-1.html
 load 407818.html
 load 410860-1.xml
 load 416734-1.html
 load 418928-1.html
 load 420620-1.html
 load 424276-1.html
 load 426987-1.html
 load 443538-1.svg
+load 450383-1.html
+load 450385-1.html
 skip load 458637-1.html # sporadically fails -- see bug 473680
 load 472593-1.html
 load 474041-1.svg
 load 483818-1.html
 load 493281-1.html
 load 493281-2.html
 load 490760-1.xhtml
 load 494810-1.html
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -568,16 +568,17 @@ public:
   static nsAdoptingString GetStringPref(const char *aPref);
   static void RegisterPrefCallback(const char *aPref,
                                    PrefChangedFunc aCallback,
                                    void * aClosure);
   static void UnregisterPrefCallback(const char *aPref,
                                      PrefChangedFunc aCallback,
                                      void * aClosure);
   static void AddBoolPrefVarCache(const char* aPref, PRBool* aVariable);
+  static void AddIntPrefVarCache(const char* aPref, PRInt32* aVariable);
   static nsIPrefBranch *GetPrefBranch()
   {
     return sPrefBranch;
   }
 
   static nsILineBreaker* LineBreaker()
   {
     return sLineBreaker;
@@ -666,16 +667,21 @@ public:
    *
    * @param aContent The image loading content.  Must not be null.
    * @param aRequest The image request [out]
    * @return the imgIContainer corresponding to the first frame of the image
    */
   static already_AddRefed<imgIContainer> GetImageFromContent(nsIImageLoadingContent* aContent, imgIRequest **aRequest = nsnull);
 
   /**
+   * Helper method to call imgIRequest::GetStaticRequest.
+   */
+  static already_AddRefed<imgIRequest> GetStaticRequest(imgIRequest* aRequest);
+
+  /**
    * Method that decides whether a content node is draggable
    *
    * @param aContent The content node to test.
    * @return whether it's draggable
    */
   static PRBool ContentIsDraggable(nsIContent* aContent);
 
   /**
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1155,16 +1155,35 @@ public:
    */
   virtual void UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents) = 0;
 
   PRUint32 EventHandlingSuppressed() const { return mEventsSuppressed; }
 
   PRBool IsDNSPrefetchAllowed() const { return mAllowDNSPrefetch; }
 
   /**
+   * PR_TRUE when this document is a static clone of a normal document.
+   * For example print preview and printing use static documents.
+   */
+  PRBool IsStaticDocument() { return mIsStaticDocument; }
+
+  /**
+   * Clones the document and subdocuments and stylesheet etc.
+   * @param aCloneContainer The container for the clone document.
+   */
+  virtual already_AddRefed<nsIDocument>
+  CreateStaticClone(nsISupports* aCloneContainer);
+
+  /**
+   * If this document is a static clone, this returns the original
+   * document.
+   */
+  nsIDocument* GetOriginalDocument() { return mOriginalDocument; }
+
+  /**
    * Called by nsParser to preload images. Can be removed and code moved
    * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
    * parser-module is linked with gklayout-module.
    */
   virtual void MaybePreLoadImage(nsIURI* uri) = 0;
 
   /**
    * Returns true if the locale used for the document specifies a direction of
@@ -1303,16 +1322,26 @@ protected:
   // (it may still be displayed, but in zombie state). Form control data
   // has been saved.
   PRPackedBool mRemovedFromDocShell;
 
   // True iff DNS prefetch is allowed for this document.  Note that if the
   // document has no window, DNS prefetch won't be performed no matter what.
   PRPackedBool mAllowDNSPrefetch;
   
+  // True when this document is a static clone of a normal document
+  PRPackedBool mIsStaticDocument;
+
+  // True while this document is being cloned to a static document.
+  PRPackedBool mCreatingStaticClone;
+
+  // If mIsStaticDocument is true, mOriginalDocument points to the original
+  // document.
+  nsCOMPtr<nsIDocument> mOriginalDocument;
+
   // The bidi options for this document.  What this bitfield means is
   // defined in nsBidiUtils.h
   PRUint32 mBidiOptions;
 
   nsCString mContentLanguage;
   nsCString mContentType;
 
   // The document's security info
--- a/content/base/public/nsIMutationObserver.h
+++ b/content/base/public/nsIMutationObserver.h
@@ -160,25 +160,22 @@ public:
    *
    * @param aDocument    The owner-document of aContent. Can be null.
    * @param aContent     The element whose attribute changed
    * @param aNameSpaceID The namespace id of the changed attribute
    * @param aAttribute   The name of the changed attribute
    * @param aModType     Whether or not the attribute was added, changed, or
    *                     removed. The constants are defined in
    *                     nsIDOMMutationEvent.h.
-   * @param aStateMask If this attribute change caused content state changes,
-   *                   the bits that changed.  Might be 0 if no bits changed.
    */
   virtual void AttributeChanged(nsIDocument* aDocument,
                                 nsIContent*  aContent,
                                 PRInt32      aNameSpaceID,
                                 nsIAtom*     aAttribute,
-                                PRInt32      aModType,
-                                PRUint32     aStateMask) = 0;
+                                PRInt32      aModType) = 0;
 
   /**
    * Notification that one or more content nodes have been appended to the
    * child list of another node in the tree.
    *
    * @param aDocument  The owner-document of aContent. Can be null.
    * @param aContainer The container that had new children appended. Is never
    *                   null.
@@ -275,18 +272,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutatio
                                      nsIAtom* aAttribute,                    \
                                      PRInt32 aModType);
 
 #define NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED                         \
     virtual void AttributeChanged(nsIDocument* aDocument,                    \
                                   nsIContent* aContent,                      \
                                   PRInt32 aNameSpaceID,                      \
                                   nsIAtom* aAttribute,                       \
-                                  PRInt32 aModType,                          \
-                                  PRUint32 aStateMask);
+                                  PRInt32 aModType);
 
 #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED                          \
     virtual void ContentAppended(nsIDocument* aDocument,                     \
                                  nsIContent* aContainer,                     \
                                  PRInt32 aNewIndexInContainer);
 
 #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED                          \
     virtual void ContentInserted(nsIDocument* aDocument,                     \
@@ -344,18 +340,17 @@ void                                    
                             PRInt32 aModType)                             \
 {                                                                         \
 }                                                                         \
 void                                                                      \
 _class::AttributeChanged(nsIDocument* aDocument,                          \
                          nsIContent* aContent,                            \
                          PRInt32 aNameSpaceID,                            \
                          nsIAtom* aAttribute,                             \
-                         PRInt32 aModType,                                \
-                         PRUint32 aStateMask)                             \
+                         PRInt32 aModType)                                \
 {                                                                         \
 }                                                                         \
 void                                                                      \
 _class::ContentAppended(nsIDocument* aDocument,                           \
                         nsIContent* aContainer,                           \
                         PRInt32 aNewIndexInContainer)                     \
 {                                                                         \
 }                                                                         \
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -798,17 +798,18 @@ public:
    */
   nsIContent* GetTextEditorRootContent(nsIEditor** aEditor = nsnull);
 
   /**
    * Get the nearest selection root, ie. the node that will be selected if the
    * user does "Select All" while the focus is in this node. Note that if this
    * node is not in an editor, the result comes from the nsFrameSelection that
    * is related to aPresShell, so the result might not be the ancestor of this
-   * node.
+   * node. Be aware that if this node and the computed selection limiter are
+   * not in same subtree, this returns the root content of the closeset subtree.
    */
   nsIContent* GetSelectionRootContent(nsIPresShell* aPresShell);
 
   virtual nsINodeList* GetChildNodesList();
   nsIContent* GetSibling(PRInt32 aOffset)
   {
     nsINode *parent = GetNodeParent();
     if (!parent) {
--- a/content/base/public/nsIObjectLoadingContent.idl
+++ b/content/base/public/nsIObjectLoadingContent.idl
@@ -32,25 +32,26 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
+interface nsIFrame;
 interface nsIObjectFrame;
 interface nsIPluginInstance;
 interface nsIDOMElement;
 interface nsIDOMClientRect;
 
 /**
  * This interface represents a content node that loads objects.
  */
-[scriptable, uuid(8afe3b08-293c-48bd-a997-321745478611)]
+[scriptable, uuid(7749d965-92f3-473e-b12d-de1e342acf1c)]
 interface nsIObjectLoadingContent : nsISupports
 {
   const unsigned long TYPE_LOADING  = 0;
   const unsigned long TYPE_IMAGE    = 1;
   const unsigned long TYPE_PLUGIN   = 2;
   const unsigned long TYPE_DOCUMENT = 3;
   const unsigned long TYPE_NULL     = 4;
 
@@ -110,9 +111,17 @@ interface nsIObjectLoadingContent : nsIS
 
   /**
    * Tells the object to paint directly in this location ignoring any
    * positioning information that may have been provided otherwise
    */
   void setAbsoluteScreenPosition(in nsIDOMElement element,
                                  in nsIDOMClientRect position,
                                  in nsIDOMClientRect clip);
+
+  /**
+   * If this object is in going to be printed, this method
+   * returns the nsIObjectFrame object which should be used when
+   * printing the plugin. The returned nsIFrame is in the original document,
+   * not in the static clone.
+   */
+  [noscript] nsIFrame getPrintFrame();
 };
--- a/content/base/public/nsIScriptElement.h
+++ b/content/base/public/nsIScriptElement.h
@@ -42,63 +42,85 @@
 #include "nsISupports.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
 #include "nsIScriptLoaderObserver.h"
 #include "nsWeakPtr.h"
 #include "nsIParser.h"
 
 #define NS_ISCRIPTELEMENT_IID \
-{ 0xa28c198e, 0x14f0, 0x42b1, \
-{ 0x8f, 0x6b, 0x0e, 0x7f, 0xca, 0xb4, 0xf4, 0xe8 } }
+{ 0xa9d5732a, 0x8c1f, 0x439d, \
+{ 0x83, 0x75, 0x3d, 0xf6, 0xa9, 0xba, 0xa3, 0x7d } }
 
 /**
  * Internal interface implemented by script elements
  */
 class nsIScriptElement : public nsIScriptLoaderObserver {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID)
 
   nsIScriptElement()
     : mLineNumber(0),
       mIsEvaluated(PR_FALSE),
       mMalformed(PR_FALSE),
       mDoneAddingChildren(PR_TRUE),
+      mFrozen(PR_FALSE),
+      mDefer(PR_FALSE),
+      mAsync(PR_FALSE),
       mCreatorParser(nsnull)
   {
   }
 
   /**
    * Content type identifying the scripting language. Can be empty, in
    * which case javascript will be assumed.
    */
   virtual void GetScriptType(nsAString& type) = 0;
     
   /**
    * Location of script source text. Can return null, in which case
    * this is assumed to be an inline script element.
    */
-  virtual already_AddRefed<nsIURI> GetScriptURI() = 0;
+  nsIURI* GetScriptURI()
+  {
+    NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
+    return mUri;
+  }
   
   /**
    * Script source text for inline script elements.
    */
   virtual void GetScriptText(nsAString& text) = 0;
 
   virtual void GetScriptCharset(nsAString& charset) = 0;
 
   /**
+   * Freezes the return values of GetScriptDeferred(), GetScriptAsync() and
+   * GetScriptURI() so that subsequent modifications to the attributes don't
+   * change execution behavior.
+   */
+  virtual void FreezeUriAsyncDefer() = 0;
+
+  /**
    * Is the script deferred. Currently only supported by HTML scripts.
    */
-  virtual PRBool GetScriptDeferred() = 0;
+  PRBool GetScriptDeferred()
+  {
+    NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
+    return mDefer;
+  }
 
   /**
    * Is the script async. Currently only supported by HTML scripts.
    */
-  virtual PRBool GetScriptAsync() = 0;
+  PRBool GetScriptAsync()
+  {
+    NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
+    return mAsync;  
+  }
 
   void SetScriptLineNumber(PRUint32 aLineNumber)
   {
     mLineNumber = aLineNumber;
   }
   PRUint32 GetScriptLineNumber()
   {
     return mLineNumber;
@@ -129,49 +151,84 @@ public:
     mCreatorParser = getter_AddRefs(NS_GetWeakReference(aParser));
   }
 
   /**
    * Informs the creator parser that the evaluation of this script is starting
    */
   void BeginEvaluating()
   {
-    // Once the async attribute is supported, don't do this if this is an
-    // async script.
     nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
     if (parser) {
       parser->BeginEvaluatingParserInsertedScript();
     }
   }
 
   /**
    * Informs the creator parser that the evaluation of this script is ending
    */
   void EndEvaluating()
   {
-    // Once the async attribute is supported, don't do this if this is an
-    // async script.
     nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
     if (parser) {
       parser->EndEvaluatingParserInsertedScript();
     }
   }
   
   /**
    * Retrieves a pointer to the creator parser if this has one or null if not
    */
   already_AddRefed<nsIParser> GetCreatorParser()
   {
     nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
     return parser.forget();
   }
 
 protected:
+  /**
+   * The start line number of the script.
+   */
   PRUint32 mLineNumber;
+  
+  /**
+   * The "already started" flag per HTML5.
+   */
   PRPackedBool mIsEvaluated;
+  
+  /**
+   * The script didn't have an end tag.
+   */
   PRPackedBool mMalformed;
+  
+  /**
+   * False if parser-inserted but the parser hasn't triggered running yet.
+   */
   PRPackedBool mDoneAddingChildren;
-  nsWeakPtr    mCreatorParser;
+
+  /**
+   * Whether src, defer and async are frozen.
+   */
+  PRPackedBool mFrozen;
+  
+  /**
+   * The effective deferredness.
+   */
+  PRPackedBool mDefer;
+  
+  /**
+   * The effective asyncness.
+   */
+  PRPackedBool mAsync;
+  
+  /**
+   * The effective src (or null if no src).
+   */
+  nsCOMPtr<nsIURI> mUri;
+  
+  /**
+   * The creator parser of a non-defer, non-async parser-inserted script.
+   */
+  nsWeakPtr mCreatorParser;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptElement, NS_ISCRIPTELEMENT_IID)
 
 #endif // nsIScriptElement_h___
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -527,17 +527,17 @@ nsContentList::GetNamedItem(const nsAStr
 {
   *aResult = NS_OK;
   return NamedItem(aName, PR_TRUE);
 }
 
 void
 nsContentList::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
                                 PRInt32 aNameSpaceID, nsIAtom* aAttribute,
-                                PRInt32 aModType, PRUint32 aStateMask)
+                                PRInt32 aModType)
 {
   NS_PRECONDITION(aContent, "Must have a content node to work with");
   NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eELEMENT),
                   "Should be an element");
   
   if (!mFunc || !mFuncMayDependOnAttr || mState == LIST_DIRTY ||
       !MayContainRelevantNodes(aContent->GetNodeParent()) ||
       !nsContentUtils::IsInSameAnonymousTree(mRootNode, aContent)) {
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -355,16 +355,19 @@ nsContentSink::ScriptAvailable(nsresult 
                mScriptElements.IndexOf(aElement) == -1,
                "script found at unexpected position");
 
   // Check if this is the element we were waiting for
   if (count == 0 || aElement != mScriptElements[count - 1]) {
     return NS_OK;
   }
 
+  NS_ASSERTION(!aElement->GetScriptDeferred(), "defer script was in mScriptElements");
+  NS_ASSERTION(!aElement->GetScriptAsync(), "async script was in mScriptElements");
+
   if (mParser && !mParser->IsParserEnabled()) {
     // make sure to unblock the parser before evaluating the script,
     // we must unblock the parser even if loading the script failed or
     // if the script was empty, if we don't, the parser will never be
     // unblocked.
     mParser->UnblockParser();
   }
 
@@ -397,16 +400,19 @@ nsContentSink::ScriptEvaluated(nsresult 
   mDeflectedCount = mPerfDeflectCount;
 
   // Check if this is the element we were waiting for
   PRInt32 count = mScriptElements.Count();
   if (count == 0 || aElement != mScriptElements[count - 1]) {
     return NS_OK;
   }
 
+  NS_ASSERTION(!aElement->GetScriptDeferred(), "defer script was in mScriptElements");
+  NS_ASSERTION(!aElement->GetScriptAsync(), "async script was in mScriptElements");
+
   // Pop the script element stack
   mScriptElements.RemoveObjectAt(count - 1); 
 
   if (NS_SUCCEEDED(aResult)) {
     PostEvaluateScript(aElement);
   }
 
   if (mParser && mParser->IsParserEnabled()) {
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1952,16 +1952,19 @@ nsContentUtils::GenerateStateKey(nsICont
   KeyAppendInt(partID, aKey);  // first append a partID
   // Make sure we can't possibly collide with an nsIStatefulFrame
   // special id of some sort
   KeyAppendInt(nsIStatefulFrame::eNoID, aKey);
   PRBool generatedUniqueKey = PR_FALSE;
 
   if (htmlDocument) {
     // Flush our content model so it'll be up to date
+    // If this becomes unnecessary and the following line is removed,
+    // please also remove the corresponding flush operation from
+    // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
     aContent->GetCurrentDoc()->FlushPendingNotifications(Flush_Content);
 
     nsContentList *htmlForms = htmlDocument->GetForms();
     nsContentList *htmlFormControls = htmlDocument->GetFormControls();
 
     NS_ENSURE_TRUE(htmlForms && htmlFormControls, NS_ERROR_OUT_OF_MEMORY);
 
     // If we have a form control and can calculate form information, use that
@@ -2499,16 +2502,26 @@ nsContentUtils::GetImageFromContent(nsII
 
   if (aRequest) {
     imgRequest.swap(*aRequest);
   }
 
   return imgContainer.forget();
 }
 
+//static
+already_AddRefed<imgIRequest>
+nsContentUtils::GetStaticRequest(imgIRequest* aRequest)
+{
+  NS_ENSURE_TRUE(aRequest, nsnull);
+  nsCOMPtr<imgIRequest> retval;
+  aRequest->GetStaticRequest(getter_AddRefs(retval));
+  return retval.forget();
+}
+
 // static
 PRBool
 nsContentUtils::ContentIsDraggable(nsIContent* aContent)
 {
   nsCOMPtr<nsIDOMNSHTMLElement> htmlElement = do_QueryInterface(aContent);
   if (htmlElement) {
     PRBool draggable = PR_FALSE;
     htmlElement->GetDraggable(&draggable);
@@ -2660,16 +2673,33 @@ BoolVarChanged(const char *aPref, void *
 void
 nsContentUtils::AddBoolPrefVarCache(const char *aPref,
                                     PRBool* aCache)
 {
   *aCache = GetBoolPref(aPref, PR_FALSE);
   RegisterPrefCallback(aPref, BoolVarChanged, aCache);
 }
 
+static int
+IntVarChanged(const char *aPref, void *aClosure)
+{
+  PRInt32* cache = static_cast<PRInt32*>(aClosure);
+  *cache = nsContentUtils::GetIntPref(aPref, 0);
+  
+  return 0;
+}
+
+void
+nsContentUtils::AddIntPrefVarCache(const char *aPref,
+                                   PRInt32* aCache)
+{
+  *aCache = GetIntPref(aPref, PR_FALSE);
+  RegisterPrefCallback(aPref, IntVarChanged, aCache);
+}
+
 static const char *gEventNames[] = {"event"};
 static const char *gSVGEventNames[] = {"evt"};
 // for b/w compat, the first name to onerror is still 'event', even though it
 // is actually the error message.  (pre this code, the other 2 were not avail.)
 // XXXmarkh - a quick lxr shows no affected code - should we correct this?
 static const char *gOnErrorNames[] = {"event", "source", "lineno"};
 
 // static
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2457,18 +2457,17 @@ nsDocument::AttributeWillChange(nsIDocum
   } else if (aAttribute == aContent->GetIDAttributeName()) {
     RemoveFromIdTable(aContent);
   }
 }
 
 void
 nsDocument::AttributeChanged(nsIDocument* aDocument,
                              nsIContent* aContent, PRInt32 aNameSpaceID,
-                             nsIAtom* aAttribute, PRInt32 aModType,
-                             PRUint32 aStateMask)
+                             nsIAtom* aAttribute, PRInt32 aModType)
 {
   NS_ASSERTION(aDocument == this, "unexpected doc");
 
   NS_ABORT_IF_FALSE(aContent, "Null content!");
   NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!");
 
   if (aNameSpaceID != kNameSpaceID_None)
     return;
@@ -3056,16 +3055,19 @@ nsDocument::doCreateShell(nsPresContext*
   }
 
   rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Note: we don't hold a ref to the shell (it holds a ref to us)
   NS_ENSURE_TRUE(mPresShells.AppendElementUnlessExists(shell),
                  NS_ERROR_OUT_OF_MEMORY);
+
+  NS_WARN_IF_FALSE(mPresShells.Length() == 1, "More than one presshell!");
+
   shell.swap(*aInstancePtrResult);
 
   return NS_OK;
 }
 
 PRBool
 nsDocument::DeleteShell(nsIPresShell* aShell)
 {
@@ -5339,18 +5341,19 @@ nsDocument::EnumerateExternalResources(n
 #ifdef MOZ_SMIL
 nsSMILAnimationController*
 nsDocument::GetAnimationController()
 {
   // We create the animation controller lazily because most documents won't want
   // one and only SVG documents and the like will call this
   if (mAnimationController)
     return mAnimationController;
-  // Refuse to create an Animation Controller if SMIL is disabled
-  if (!NS_SMILEnabled())
+  // Refuse to create an Animation Controller if SMIL is disabled, and also
+  // for data documents.
+  if (!NS_SMILEnabled() || mLoadedAsData)
     return nsnull;
 
   mAnimationController = NS_NewSMILAnimationController(this);
   
   // If there's a presContext then check the animation mode and pause if
   // necessary.
   nsIPresShell *shell = GetPrimaryShell();
   if (mAnimationController && shell) {
@@ -7582,26 +7585,43 @@ nsDocument::QuerySelectorAll(const nsASt
                              nsIDOMNodeList **aReturn)
 {
   return nsGenericElement::doQuerySelectorAll(this, aSelector, aReturn);
 }
 
 nsresult
 nsDocument::CloneDocHelper(nsDocument* clone) const
 {
+  clone->mIsStaticDocument = mCreatingStaticClone;
+
   // Init document
   nsresult rv = clone->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Set URI/principal
   clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI());
   // Must set the principal first, since SetBaseURI checks it.
   clone->SetPrincipal(NodePrincipal());
   clone->mDocumentBaseURI = mDocumentBaseURI;
 
+  if (mCreatingStaticClone) {
+    nsCOMPtr<nsIChannel> channel = GetChannel();
+    nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
+    if (channel && loadGroup) {
+      clone->Reset(channel, loadGroup);
+    } else {
+      nsIURI* uri = static_cast<const nsIDocument*>(this)->GetDocumentURI();
+      if (uri) {
+        clone->ResetToURI(uri, loadGroup, NodePrincipal());
+      }
+    }
+    nsCOMPtr<nsISupports> container = GetContainer();
+    clone->SetContainer(container);
+  }
+
   // Set scripting object
   PRBool hasHadScriptObject = PR_TRUE;
   nsIScriptGlobalObject* scriptObject =
     GetScriptHandlingObject(hasHadScriptObject);
   NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
   clone->SetScriptHandlingObject(scriptObject);
 
   // Make the clone a data document
@@ -7816,8 +7836,72 @@ void
 nsIDocument::EnumerateFreezableElements(FreezableElementEnumerator aEnumerator,
                                         void* aData)
 {
   if (!mFreezableElements)
     return;
   EnumerateFreezablesData data = { aEnumerator, aData };
   mFreezableElements->EnumerateEntries(EnumerateFreezables, &data);
 }
+
+already_AddRefed<nsIDocument>
+nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
+{
+  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(this);
+  NS_ENSURE_TRUE(domDoc, nsnull);
+  mCreatingStaticClone = PR_TRUE;
+
+  // Make document use different container during cloning.
+  nsCOMPtr<nsISupports> originalContainer = GetContainer();
+  SetContainer(aCloneContainer);
+  nsCOMPtr<nsIDOMNode> clonedNode;
+  nsresult rv = domDoc->CloneNode(PR_TRUE, getter_AddRefs(clonedNode));
+  SetContainer(originalContainer);
+
+  nsCOMPtr<nsIDocument> clonedDoc;
+  if (NS_SUCCEEDED(rv)) {
+    clonedDoc = do_QueryInterface(clonedNode);
+    nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
+    if (clonedDOMDoc) {
+      clonedDoc->mOriginalDocument = this;
+      PRInt32 sheetsCount = GetNumberOfStyleSheets();
+      for (PRInt32 i = 0; i < sheetsCount; ++i) {
+        nsCOMPtr<nsICSSStyleSheet> sheet =
+          do_QueryInterface(GetStyleSheetAt(i));
+        if (sheet) {
+          PRBool applicable = PR_TRUE;
+          sheet->GetApplicable(applicable);
+          if (applicable) {
+            nsCOMPtr<nsICSSStyleSheet> clonedSheet;
+            sheet->Clone(nsnull, nsnull, clonedDoc, nsnull,
+                         getter_AddRefs(clonedSheet));
+            NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
+            if (clonedSheet) {
+              clonedDoc->AddStyleSheet(clonedSheet);
+            }
+          }
+        }
+      }
+
+      sheetsCount = GetNumberOfCatalogStyleSheets();
+      for (PRInt32 i = 0; i < sheetsCount; ++i) {
+        nsCOMPtr<nsICSSStyleSheet> sheet =
+          do_QueryInterface(GetCatalogStyleSheetAt(i));
+        if (sheet) {
+          PRBool applicable = PR_TRUE;
+          sheet->GetApplicable(applicable);
+          if (applicable) {
+            nsCOMPtr<nsICSSStyleSheet> clonedSheet;
+            sheet->Clone(nsnull, nsnull, clonedDoc, nsnull,
+                         getter_AddRefs(clonedSheet));
+            NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
+            if (clonedSheet) {
+              clonedDoc->AddCatalogStyleSheet(clonedSheet);
+            }
+          }
+        }
+      }
+    }
+  }
+  mCreatingStaticClone = PR_FALSE;
+  return clonedDoc.forget();
+}
+
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -89,16 +89,18 @@
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 
 #include "nsGkAtoms.h"
 #include "nsINameSpaceManager.h"
 
 #include "nsThreadUtils.h"
+#include "nsICSSStyleSheet.h"
+#include "nsIContentViewer.h"
 #include "nsIView.h"
 
 #ifdef MOZ_WIDGET_GTK2
 #include "mozcontainer.h"
 
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #endif
@@ -156,19 +158,21 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 nsFrameLoader*
 nsFrameLoader::Create(nsIContent* aOwner)
 {
   NS_ENSURE_TRUE(aOwner, nsnull);
-  nsIDocument* doc = aOwner->GetCurrentDoc();
+  nsIDocument* doc = aOwner->GetOwnerDoc();
   NS_ENSURE_TRUE(doc && !doc->GetDisplayDocument() &&
-                 !doc->IsLoadedAsData(), nsnull);
+                 ((!doc->IsLoadedAsData() && aOwner->GetCurrentDoc()) ||
+                   doc->IsStaticDocument()),
+                 nsnull);
 
   return new nsFrameLoader(aOwner);
 }
 
 NS_IMETHODIMP
 nsFrameLoader::LoadFrame()
 {
   NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED);
@@ -178,17 +182,17 @@ nsFrameLoader::LoadFrame()
 
   src.Trim(" \t\n\r");
 
   if (src.IsEmpty()) {
     src.AssignLiteral("about:blank");
   }
 
   nsIDocument* doc = mOwnerContent->GetOwnerDoc();
-  if (!doc) {
+  if (!doc || doc->IsStaticDocument()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> base_uri = mOwnerContent->GetBaseURI();
   const nsAFlatCString &doc_charset = doc->GetDocumentCharacterSet();
   const char *charset = doc_charset.IsEmpty() ? nsnull : doc_charset.get();
 
   nsCOMPtr<nsIURI> uri;
@@ -1102,28 +1106,29 @@ nsFrameLoader::MaybeCreateDocShell()
     mRemoteFrame = true;
     return NS_OK;
   }
 #endif
 
   // Get our parent docshell off the document of mOwnerContent
   // XXXbz this is such a total hack.... We really need to have a
   // better setup for doing this.
-  nsIDocument* doc = mOwnerContent->GetDocument();
-  if (!doc) {
+  nsIDocument* doc = mOwnerContent->GetOwnerDoc();
+  if (!doc || !(doc->IsStaticDocument() || mOwnerContent->IsInDoc())) {
     return NS_ERROR_UNEXPECTED;
   }
 
   if (doc->GetDisplayDocument()) {
     // Don't allow subframe loads in external reference documents
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsCOMPtr<nsIWebNavigation> parentAsWebNav =
-    do_GetInterface(doc->GetScriptGlobalObject());
+  nsCOMPtr<nsISupports> container =
+    doc->GetContainer();
+  nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(container);
 
   // Create the docshell...
   mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   // Get the frame name and tell the docshell about it.
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
@@ -1503,8 +1508,32 @@ nsFrameLoader::ActivateFrameEvent(const 
   if (mChildProcess) {
     mChildProcess->SendactivateFrameEvent(nsString(aType), aCapture);
     return NS_OK;
   }
 #endif
   return NS_ERROR_FAILURE;
 }
 
+nsresult
+nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
+{
+  nsFrameLoader* dest = static_cast<nsFrameLoader*>(aDest);
+  dest->MaybeCreateDocShell();
+  NS_ENSURE_STATE(dest->mDocShell);
+
+  nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(dest->mDocShell);
+  nsCOMPtr<nsIContentViewer> viewer;
+  dest->mDocShell->GetContentViewer(getter_AddRefs(viewer));
+  NS_ENSURE_STATE(viewer);
+
+  nsCOMPtr<nsIDocShell> origDocShell;
+  GetDocShell(getter_AddRefs(origDocShell));
+  nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(origDocShell);
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+  NS_ENSURE_STATE(doc);
+  nsCOMPtr<nsIDocument> clonedDoc = doc->CreateStaticClone(dest->mDocShell);
+  nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
+
+  viewer->SetDOMDocument(clonedDOMDoc);
+  return NS_OK;
+}
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -99,31 +99,35 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
   NS_DECL_NSIFRAMELOADER
   NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI);
   nsresult ReallyStartLoading();
   void Finalize();
   nsIDocShell* GetExistingDocShell() { return mDocShell; }
 
+  nsresult CreateStaticClone(nsIFrameLoader* aDest);
+
   /**
    * Called from the layout frame associated with this frame loader;
    * this notifies us to hook up with the widget and view.
    */
   bool Show(PRInt32 marginWidth, PRInt32 marginHeight,
             PRInt32 scrollbarPrefX, PRInt32 scrollbarPrefY,
             nsIFrameFrame* frame);
 
   /**
    * Called from the layout frame associated with this frame loader, when
    * the frame is being torn down; this notifies us that out widget and view
    * are going away and we should unhook from them.
    */
   void Hide();
 
+  nsresult CloneForStatic(nsIFrameLoader* aOriginal);
+
   // The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation.  A
   // frame loader owner needs to call this, and pass in the two references to
   // nsRefPtrs for frame loaders that need to be swapped.
   nsresult SwapWithOtherLoader(nsFrameLoader* aOther,
                                nsRefPtr<nsFrameLoader>& aFirstToSwap,
                                nsRefPtr<nsFrameLoader>& aSecondToSwap);
 
 #ifdef MOZ_IPC
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -367,16 +367,30 @@ static nsIEditor* GetHTMLEditor(nsPresCo
       NS_FAILED(editorDocShell->GetEditable(&isEditable)) || !isEditable)
     return nsnull;
 
   nsCOMPtr<nsIEditor> editor;
   editorDocShell->GetEditor(getter_AddRefs(editor));
   return editor;
 }
 
+static nsIContent* GetRootForContentSubtree(nsIContent* aContent)
+{
+  NS_ENSURE_TRUE(aContent, nsnull);
+  nsIContent* stop = aContent->GetBindingParent();
+  while (aContent) {
+    nsIContent* parent = aContent->GetParent();
+    if (parent == stop) {
+      break;
+    }
+    aContent = parent;
+  }
+  return aContent;
+}
+
 nsIContent*
 nsINode::GetSelectionRootContent(nsIPresShell* aPresShell)
 {
   NS_ENSURE_TRUE(aPresShell, nsnull);
 
   if (IsNodeOfType(eDOCUMENT))
     return static_cast<nsIDocument*>(this)->GetRootContent();
   if (!IsNodeOfType(eCONTENT))
@@ -392,40 +406,52 @@ nsINode::GetSelectionRootContent(nsIPres
   }
 
   nsPresContext* presContext = aPresShell->GetPresContext();
   if (presContext) {
     nsIEditor* editor = GetHTMLEditor(presContext);
     if (editor) {
       // This node is in HTML editor.
       nsIDocument* doc = GetCurrentDoc();
-      if (!doc || doc->HasFlag(NODE_IS_EDITABLE) || !HasFlag(NODE_IS_EDITABLE))
-        return GetEditorRootContent(editor);
+      if (!doc || doc->HasFlag(NODE_IS_EDITABLE) ||
+          !HasFlag(NODE_IS_EDITABLE)) {
+        nsIContent* editorRoot = GetEditorRootContent(editor);
+        return nsContentUtils::IsInSameAnonymousTree(this, editorRoot) ?
+                 editorRoot :
+                 GetRootForContentSubtree(static_cast<nsIContent*>(this));
+      }
       // If the current document is not editable, but current content is
       // editable, we should assume that the child of the nearest non-editable
       // ancestor is selection root.
       nsIContent* content = static_cast<nsIContent*>(this);
       for (nsIContent* parent = GetParent();
            parent && parent->HasFlag(NODE_IS_EDITABLE);
            parent = content->GetParent())
         content = parent;
       return content;
     }
   }
 
   nsCOMPtr<nsFrameSelection> fs = aPresShell->FrameSelection();
   nsIContent* content = fs->GetLimiter();
-  if (content)
-    return content;
-  content = fs->GetAncestorLimiter();
-  if (content)
-    return content;
-  nsIDocument* doc = aPresShell->GetDocument();
-  NS_ENSURE_TRUE(doc, nsnull);
-  return doc->GetRootContent();
+  if (!content) {
+    content = fs->GetAncestorLimiter();
+    if (!content) {
+      nsIDocument* doc = aPresShell->GetDocument();
+      NS_ENSURE_TRUE(doc, nsnull);
+      content = doc->GetRootContent();
+      if (!content)
+        return nsnull;
+    }
+  }
+
+  // This node might be in another subtree, if so, we should find this subtree's
+  // root.  Otherwise, we can return the content simply.
+  return nsContentUtils::IsInSameAnonymousTree(this, content) ?
+           content : GetRootForContentSubtree(static_cast<nsIContent*>(this));
 }
 
 nsINodeList*
 nsINode::GetChildNodesList()
 {
   nsSlots *slots = GetSlots();
   if (!slots) {
     return nsnull;
@@ -4427,18 +4453,17 @@ nsGenericElement::SetAttrAndNotify(PRInt
   }
 
   if (aNotify) {
     stateMask = stateMask ^ PRUint32(IntrinsicState());
     if (stateMask && document) {
       MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
       document->ContentStatesChanged(this, nsnull, stateMask);
     }
-    nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, modType,
-                                  stateMask);
+    nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, modType);
   }
 
   if (aNamespaceID == kNameSpaceID_XMLEvents && 
       aName == nsGkAtoms::event && mNodeInfo->GetDocument()) {
     mNodeInfo->GetDocument()->AddXMLEventsContent(this);
   }
   if (aValueForAfterSetAttr) {
     rv = AfterSetAttr(aNamespaceID, aName, aValueForAfterSetAttr, aNotify);
@@ -4689,18 +4714,17 @@ nsGenericElement::UnsetAttr(PRInt32 aNam
 
   if (aNotify) {
     stateMask = stateMask ^ PRUint32(IntrinsicState());
     if (stateMask && document) {
       MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
       document->ContentStatesChanged(this, nsnull, stateMask);
     }
     nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
-                                  nsIDOMMutationEvent::REMOVAL,
-                                  stateMask);
+                                  nsIDOMMutationEvent::REMOVAL);
   }
 
   rv = AfterSetAttr(aNameSpaceID, aName, nsnull, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (hasMutationListeners) {
     mozAutoRemovableBlockerRemover blockerRemover(GetOwnerDoc());
 
@@ -5137,38 +5161,55 @@ nsGenericElement::PostHandleEventForLink
 
 void
 nsGenericElement::GetLinkTarget(nsAString& aTarget)
 {
   aTarget.Truncate();
 }
 
 // NOTE: The aPresContext pointer is NOT addrefed.
+// *aSelectorList might be null even if NS_OK is returned; this
+// happens when all the selectors were pseudo-element selectors.
 static nsresult
 ParseSelectorList(nsINode* aNode,
                   const nsAString& aSelectorString,
                   nsCSSSelectorList** aSelectorList,
                   nsPresContext** aPresContext)
 {
   NS_ENSURE_ARG(aNode);
 
   nsIDocument* doc = aNode->GetOwnerDoc();
   NS_ENSURE_STATE(doc);
 
   nsCOMPtr<nsICSSParser> parser;
   nsresult rv = doc->CSSLoader()->GetParserFor(nsnull, getter_AddRefs(parser));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsCSSSelectorList* selectorList;
   rv = parser->ParseSelectorString(aSelectorString,
                                    doc->GetDocumentURI(),
                                    0, // XXXbz get the right line number!
-                                   aSelectorList);
+                                   &selectorList);
   doc->CSSLoader()->RecycleParser(parser);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Filter out pseudo-element selectors from selectorList
+  nsCSSSelectorList** slot = &selectorList;
+  do {
+    nsCSSSelectorList* cur = *slot;
+    if (cur->mSelectors->IsPseudoElement()) {
+      *slot = cur->mNext;
+      cur->mNext = nsnull;
+      delete cur;
+    } else {
+      slot = &cur->mNext;
+    }
+  } while (*slot);
+  *aSelectorList = selectorList;
+
   // It's not strictly necessary to have a prescontext here, but it's
   // a bit of an optimization for various stuff.
   *aPresContext = nsnull;
   nsIPresShell* shell = doc->GetPrimaryShell();
   if (shell) {
     *aPresContext = shell->GetPresContext();
   }
 
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -196,17 +196,16 @@ GK_ATOM(circle, "circle")
 GK_ATOM(cite, "cite")
 GK_ATOM(_class, "class")
 GK_ATOM(classid, "classid")
 GK_ATOM(clear, "clear")
 GK_ATOM(click, "click")
 GK_ATOM(clickcount, "clickcount")
 GK_ATOM(movetoclick, "movetoclick")
 GK_ATOM(clip, "clip")
-GK_ATOM(clonedTextForPrint, "clonedTextForPrint")
 GK_ATOM(close, "close")
 GK_ATOM(closed, "closed")
 GK_ATOM(closemenu, "closemenu")
 GK_ATOM(coalesceduplicatearcs, "coalesceduplicatearcs")
 GK_ATOM(code, "code")
 GK_ATOM(codebase, "codebase")
 GK_ATOM(codetype, "codetype")
 GK_ATOM(col, "col")
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -982,8 +982,24 @@ nsImageLoadingContent::SetBlockingOnload
       doc->BlockOnload();
     else
       doc->UnblockOnload(PR_FALSE);
 
     // Update our state
     mBlockingOnload = aBlocking;
   }
 }
+
+void
+nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) const
+{
+  aDest->mCurrentRequest = nsContentUtils::GetStaticRequest(mCurrentRequest);
+  aDest->mForcedImageState = mForcedImageState;
+  aDest->mImageBlockingStatus = mImageBlockingStatus;
+  aDest->mLoadingEnabled = mLoadingEnabled;
+  aDest->mStartingLoad = mStartingLoad;
+  aDest->mIsImageStateForced = mIsImageStateForced;
+  aDest->mLoading = mLoading;
+  aDest->mBroken = mBroken;
+  aDest->mUserDisabled = mUserDisabled;
+  aDest->mSuppressed = mSuppressed;
+}
+
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -242,19 +242,20 @@ private:
   /**
    * Method to fire an event once we know what's going on with the image load.
    *
    * @param aEventType "load" or "error" depending on how things went
    */
   nsresult FireEvent(const nsAString& aEventType);
   class Event;
   friend class Event;
+protected:
+  void CreateStaticImageClone(nsImageLoadingContent* aDest) const;
 
   /* MEMBERS */
-protected:
   nsCOMPtr<imgIRequest> mCurrentRequest;
   nsCOMPtr<imgIRequest> mPendingRequest;
   nsCOMPtr<nsIURI>      mCurrentURI;
 
 private:
   /**
    * Typically we will have only one observer (our frame in the screen
    * prescontext), so we want to only make space for one and to
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -113,23 +113,22 @@ nsNodeUtils::AttributeWillChange(nsICont
                              (doc, aContent, aNameSpaceID, aAttribute,
                               aModType));
 }
 
 void
 nsNodeUtils::AttributeChanged(nsIContent* aContent,
                               PRInt32 aNameSpaceID,
                               nsIAtom* aAttribute,
-                              PRInt32 aModType,
-                              PRUint32 aStateMask)
+                              PRInt32 aModType)
 {
   nsIDocument* doc = aContent->GetOwnerDoc();
   IMPL_MUTATION_NOTIFICATION(AttributeChanged, aContent,
                              (doc, aContent, aNameSpaceID, aAttribute,
-                              aModType, aStateMask));
+                              aModType));
 }
 
 void
 nsNodeUtils::ContentAppended(nsIContent* aContainer,
                              PRInt32 aNewIndexInContainer)
 {
   nsIDocument* doc = aContainer->GetOwnerDoc();
 
--- a/content/base/src/nsNodeUtils.h
+++ b/content/base/src/nsNodeUtils.h
@@ -87,24 +87,22 @@ public:
                                   PRInt32 aModType);
 
   /**
    * Send AttributeChanged notifications to nsIMutationObservers.
    * @param aContent      Node whose data changed
    * @param aNameSpaceID  Namespace of changed attribute
    * @param aAttribute    Local-name of changed attribute
    * @param aModType      Type of change (add/change/removal)
-   * @param aStateMask    States which changed
    * @see nsIMutationObserver::AttributeChanged
    */
   static void AttributeChanged(nsIContent* aContent,
                                PRInt32 aNameSpaceID,
                                nsIAtom* aAttribute,
-                               PRInt32 aModType,
-                               PRUint32 aStateMask);
+                               PRInt32 aModType);
 
   /**
    * Send ContentAppended notifications to nsIMutationObservers
    * @param aContainer           Node into which new child/children were added
    * @param aNewIndexInContainer Index of first new child
    * @see nsIMutationObserver::ContentAppended
    */
   static void ContentAppended(nsIContent* aContainer,
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -807,16 +807,24 @@ nsObjectLoadingContent::EnsureInstantiat
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
 {
   LOG(("OBJLC [%p]: Got frame %p (mInstantiating=%i)\n", this, aFrame,
        mInstantiating));
 
+  nsCOMPtr<nsIContent> thisContent = 
+    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+  NS_ASSERTION(thisContent, "must be a content");
+  nsIDocument* doc = thisContent->GetOwnerDoc();
+  if (!doc || doc->IsStaticDocument()) {
+    return NS_OK;
+  }
+  
   // "revoke" any existing instantiate event as it likely has out of
   // date data (frame pointer etc).
   mPendingInstantiateEvent = nsnull;
 
   nsCOMPtr<nsIPluginInstance> instance;
   aFrame->GetPluginInstance(*getter_AddRefs(instance));
 
   if (instance) {
@@ -1093,17 +1101,19 @@ nsObjectLoadingContent::LoadObject(nsIUR
       mFinalListener->OnStopRequest(mChannel, nsnull, NS_BINDING_ABORTED);
       mFinalListener = nsnull;
     }
     mChannel = nsnull;
   }
 
   // Security checks
   if (doc->IsLoadedAsData()) {
-    Fallback(PR_FALSE);
+    if (!doc->IsStaticDocument()) {
+      Fallback(PR_FALSE);
+    }
     return NS_OK;
   }
 
   // Can't do security checks without a URI - hopefully the plugin will take
   // care of that
   // Null URIs happen when the URL to load is specified via other means than the
   // data/src attribute, for example via custom <param> elements.
   if (aURI) {
@@ -1871,16 +1881,50 @@ nsObjectLoadingContent::GetPluginDisable
   nsresult rv = host->IsPluginEnabledForType(aContentType.get());
   if (rv == NS_ERROR_PLUGIN_DISABLED)
     return ePluginDisabled;
   if (rv == NS_ERROR_PLUGIN_BLOCKLISTED)
     return ePluginBlocklisted;
   return ePluginUnsupported;
 }
 
+void
+nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const
+{
+  nsImageLoadingContent::CreateStaticImageClone(aDest);
+
+  aDest->mType = mType;
+  nsObjectLoadingContent* thisObj = const_cast<nsObjectLoadingContent*>(this);
+  if (thisObj->mPrintFrame.IsAlive()) {
+    aDest->mPrintFrame = thisObj->mPrintFrame;
+  } else {
+    nsIObjectFrame* frame =
+      const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame(eDontFlush);
+    nsIFrame* f = do_QueryFrame(frame);
+    aDest->mPrintFrame = f;
+  }
+
+  if (mFrameLoader) {
+    nsCOMPtr<nsIContent> content =
+      do_QueryInterface(static_cast<nsIImageLoadingContent*>((aDest)));
+    nsFrameLoader* fl = nsFrameLoader::Create(content);
+    if (fl) {
+      aDest->mFrameLoader = fl;
+      mFrameLoader->CreateStaticClone(fl);
+    }
+  }
+}
+
+NS_IMETHODIMP
+nsObjectLoadingContent::GetPrintFrame(nsIFrame** aFrame)
+{
+  *aFrame = mPrintFrame.GetFrame();
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsObjectLoadingContent::SetAbsoluteScreenPosition(nsIDOMElement* element,
                                                   nsIDOMClientRect* position,
                                                   nsIDOMClientRect* clip)
 {
   nsIObjectFrame* frame = GetExistingFrame(eFlushLayout);
   if (!frame)
     return NS_ERROR_NOT_AVAILABLE;
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -48,16 +48,17 @@
 #include "nsImageLoadingContent.h"
 #include "nsIStreamListener.h"
 #include "nsFrameLoader.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIChannelEventSink.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIRunnable.h"
 #include "nsIChannelClassifier.h"
+#include "nsIFrame.h"
 
 class nsAsyncInstantiateEvent;
 class AutoNotifier;
 class AutoFallback;
 class AutoSetInstantiatingToFalse;
 
 enum PluginSupportState {
   ePluginUnsupported,  // The plugin is not supported (not installed, say)
@@ -218,16 +219,17 @@ class nsObjectLoadingContent : public ns
      * document.
      *
      * XXX This is a temporary workaround for docshell suckyness
      */
     void RemovedFromDocument();
 
     void Traverse(nsCycleCollectionTraversalCallback &cb);
 
+    void CreateStaticClone(nsObjectLoadingContent* aDest) const;
   private:
     /**
      * Check whether the given request represents a successful load.
      */
     static PRBool IsSuccessfulRequest(nsIRequest* aRequest);
 
     /**
      * Check whether the URI can be handled internally.
@@ -417,13 +419,15 @@ class nsObjectLoadingContent : public ns
      */
     PRPackedBool                mInstantiating : 1;
     // Blocking status from content policy
     PRPackedBool                mUserDisabled  : 1;
     PRPackedBool                mSuppressed    : 1;
     // A specific state that caused us to fallback
     PluginSupportState          mPluginState;
 
+    nsWeakFrame                 mPrintFrame;
+
     friend class nsAsyncInstantiateEvent;
 };
 
 
 #endif
--- a/content/base/src/nsScriptElement.cpp
+++ b/content/base/src/nsScriptElement.cpp
@@ -116,18 +116,17 @@ nsScriptElement::CharacterDataChanged(ns
   MaybeProcessScript();
 }
 
 void
 nsScriptElement::AttributeChanged(nsIDocument* aDocument,
                                   nsIContent* aContent,
                                   PRInt32 aNameSpaceID,
                                   nsIAtom* aAttribute,
-                                  PRInt32 aModType,
-                                  PRUint32 aStateMask)
+                                  PRInt32 aModType)
 {
   MaybeProcessScript();
 }
 
 void
 nsScriptElement::ContentAppended(nsIDocument* aDocument,
                                  nsIContent* aContainer,
                                  PRInt32 aNewIndexInContainer)
@@ -176,16 +175,18 @@ nsScriptElement::MaybeProcessScript()
   NS_ASSERTION(cont->DebugGetSlots()->mMutationObservers.Contains(this),
                "You forgot to add self as observer");
 
   if (mIsEvaluated || !mDoneAddingChildren || !cont->IsInDoc() ||
       mMalformed || !HasScriptContent()) {
     return NS_OK;
   }
 
+  FreezeUriAsyncDefer();
+
   if (InNonScriptingContainer(cont)) {
     // Make sure to flag ourselves as evaluated
     mIsEvaluated = PR_TRUE;
     return NS_OK;
   }
 
   nsresult scriptresult = NS_OK;
   nsRefPtr<nsScriptLoader> loader = cont->GetOwnerDoc()->ScriptLoader();
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -217,17 +217,19 @@ void
 nsStyledElement::ParseStyleAttribute(nsIContent* aContent,
                                      const nsAString& aValue,
                                      nsAttrValue& aResult,
                                      PRBool aForceInDataDoc)
 {
   nsresult result = NS_OK;
   nsIDocument* doc = aContent->GetOwnerDoc();
 
-  if (doc && (aForceInDataDoc || !doc->IsLoadedAsData())) {
+  if (doc && (aForceInDataDoc ||
+              !doc->IsLoadedAsData() ||
+              doc->IsStaticDocument())) {
     PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise
 
     if (!aContent->IsInNativeAnonymousSubtree()) {  // native anonymous content
                                                     // always assumes CSS
       nsAutoString styleType;
       doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType);
       if (!styleType.IsEmpty()) {
         static const char textCssStr[] = "text/css";
--- a/content/base/src/nsTextNode.cpp
+++ b/content/base/src/nsTextNode.cpp
@@ -329,18 +329,17 @@ nsAttributeTextNode::UnbindFromTree(PRBo
   nsTextNode::UnbindFromTree(aDeep, aNullParent);
 }
 
 void
 nsAttributeTextNode::AttributeChanged(nsIDocument* aDocument,
                                       nsIContent* aContent,
                                       PRInt32 aNameSpaceID,
                                       nsIAtom* aAttribute,
-                                      PRInt32 aModType,
-                                      PRUint32 aStateMask)
+                                      PRInt32 aModType)
 {
   if (aNameSpaceID == mNameSpaceID && aAttribute == mAttrName &&
       aContent == mGrandparent) {
     // Since UpdateText notifies, do it asynchronously.  Note that if we get
     // unbound while the event is up that's ok -- we'll just have no
     // grandparent when it fires, and will do nothing.    
     // XXXbz ideally we'd either process this on layout flushes or do it right
     // after nsIMutationObserver notifications are over or something, instead
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -149,16 +149,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug405182.html \
 		test_bug403841.html \
 		test_bug409380.html \
 		test_bug410229.html \
 		test_bug413974.html \
 		test_bug415860.html \
 		test_bug414190.html \
 		test_bug414796.html \
+		test_bug527896.html \
 		test_bug416317-1.html \
 		test_bug416317-2.html \
 		test_XHRSendData.html \
 		file_XHRSendData.sjs \
 		file_XHRSendData_doc.xml \
 		file_XHRSendData_doc.xml^headers^ \
 		file_bug416317.xhtml \
 		test_bug416383.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug527896.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=527896
+-->
+<head>
+  <title>Test for Bug 527896</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" />
+</head>
+<body onload='done();'>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=527896">Mozilla Bug 527896</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 527896 **/
+
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+          .getService(Components.interfaces.nsIPrefBranch);
+var gOriginalHtml5Pref = prefs.getBoolPref("html5.enable");
+prefs.setBoolPref("html5.enable", true);
+
+SimpleTest.waitForExplicitFinish();
+
+var docWrittenSrcExecuted = false;
+var scriptInsertedSrcExecuted = false;
+
+// the iframe test runs with the HTML5 parser
+
+var iframe = document.getElementsByTagName('iframe')[0];
+iframe.contentWindow.document.open();
+iframe.contentWindow.document.write("<!DOCTYPE html>");
+iframe.contentWindow.document.write("<body><script id =\"thescript\" src=\"data:text/javascript,parent.docWrittenSrcExecuted = true;\">");
+
+// now remove the src attribute before the end tag is parsed
+iframe.contentWindow.document.getElementById('thescript').removeAttribute('src');
+
+iframe.contentWindow.document.write("parent.ok(false, \"Content executed.\");");
+iframe.contentWindow.document.write("<\/script>");
+iframe.contentWindow.document.close();
+
+// the insertion test runs with the default HTML parser since it's in this document itself!
+
+var div = document.getElementById('content');
+var script = document.createElement('script');
+div.appendChild(script); // this shouldn't yet freeze the script node nor run it
+script.setAttribute("src", "data:text/javascript,scriptInsertedSrcExecuted = true;");
+
+todo(false, "Add SVG tests after bug 528442.");
+
+function done() {
+  ok(docWrittenSrcExecuted, "document.written src didn't execute");
+  ok(scriptInsertedSrcExecuted, "script-inserted src didn't execute");
+
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+            .getService(Components.interfaces.nsIPrefBranch);
+  prefs.setBoolPref("html5.enable", gOriginalHtml5Pref);
+
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -59,49 +59,55 @@ CPPSRCS += \
 	DocumentRendererChild.cpp \
 	$(NULL)
 endif
 
 # Canvas 3D Pieces
 
 ifdef MOZ_WEBGL
 
+ifeq (1_1,$(MOZ_X11)_$(NS_OSSO))
+WEBGL_PLATFORM = EGL
+DEFINES += -DUSE_GLES2
+endif
+
+ifeq (1_,$(MOZ_X11)_$(NS_OSSO))
+WEBGL_PLATFORM = GLX
+EXTRA_DSO_LIBS += X11
+endif
+
+
+ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
+ifdef WINCE
+WEBGL_PLATFORM = EGL
+DEFINES += -DUSE_GLES2
+else
+WEBGL_PLATFORM = WGL
+endif
+endif
+
+ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
+WEBGL_PLATFORM = CGL
+endif
+
 CPPSRCS += \
 	WebGLArrays.cpp \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
 	WebGLContextValidate.cpp \
 	NativeJSContext.cpp \
 	glwrap.cpp \
 	nsGLPbuffer.cpp \
 	nsGLPbufferOSMesa.cpp \
 	SimpleBuffer.cpp \
 	$(NULL)
 
-ifdef MOZ_X11
-EXTRA_DSO_LIBS += X11
-CPPSRCS += nsGLPbufferGLX.cpp
-DEFINES += -DUSE_GLX
-endif
-
-ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
-ifdef WINCE
-CPPSRCS += nsGLPbufferEGL.cpp
-DEFINES += -DUSE_EGL
-else
-CPPSRCS += nsGLPbufferWGL.cpp
-DEFINES += -DUSE_WGL
-endif
-endif
-
-ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
-CPPSRCS += nsGLPbufferCGL.cpp
-DEFINES += -DUSE_CGL
-endif
+CPPSRCS += nsGLPbuffer$(WEBGL_PLATFORM).cpp
+DEFINES += -DUSE_$(WEBGL_PLATFORM)
 
 else
 
 CPPSRCS += WebGLContextNotSupported.cpp
 
 endif
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -95,23 +95,23 @@ WebGLContext::SetCanvasElement(nsICanvas
         rv = prefBranch->GetBoolPref("software_render", &val);
         if (NS_SUCCEEDED(rv))
             forceSoftware = val;
     }
 
     LogMessage("Canvas 3D: creating PBuffer...");
 
     if (!forceSoftware) {
-#if defined(WINCE)
+#if defined(USE_EGL)
         mGLPbuffer = new nsGLPbufferEGL();
-#elif defined(XP_WIN)
+#elif defined(USE_WGL)
         mGLPbuffer = new nsGLPbufferWGL();
-#elif defined(XP_UNIX) && defined(MOZ_X11)
+#elif defined(USE_GLX)
         mGLPbuffer = new nsGLPbufferGLX();
-#elif defined(XP_MACOSX)
+#elif defined(USE_CGL)
         mGLPbuffer = new nsGLPbufferCGL();
 #else
         mGLPbuffer = nsnull;
 #endif
 
         if (mGLPbuffer && !mGLPbuffer->Init(this))
             mGLPbuffer = nsnull;
     }
@@ -248,24 +248,30 @@ WebGLContext::Render(gfxContext *ctx, gf
         mCanvasElement->GLWidgetSwapBuffers();
         mCanvasElement->GLWidgetEndDrawing();
     } else
 #endif
     {
         nsRefPtr<gfxASurface> surf = mGLPbuffer->ThebesSurface();
         if (!surf)
             return NS_OK;
-
         // XXX we can optimize this on win32 at least, by creating an upside-down
         // DIB.
         nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
+
+#if defined(USE_EGL) && defined(MOZ_X11)
+        if (getenv("IMAGE")) {
+#endif
         gfxMatrix m;
         m.Translate(gfxPoint(0.0, mGLPbuffer->Height()));
         m.Scale(1.0, -1.0);
         pat->SetMatrix(m);
+#if defined(USE_EGL) && defined(MOZ_X11)
+        }
+#endif
 
         // XXX I don't want to use PixelSnapped here, but layout doesn't guarantee
         // pixel alignment for this stuff!
         ctx->NewPath();
         ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
         ctx->Fill();
     }
 
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -280,20 +280,22 @@ protected:
     // textures bound to 
     nsTArray<WebGLObjectRefPtr<WebGLTexture> > mBound2DTextures;
     nsTArray<WebGLObjectRefPtr<WebGLTexture> > mBoundCubeMapTextures;
 
     WebGLObjectRefPtr<WebGLBuffer> mBoundArrayBuffer;
     WebGLObjectRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
     WebGLObjectRefPtr<WebGLProgram> mCurrentProgram;
 
-    nsTArray<nsRefPtr<WebGLFramebuffer> > mBoundColorFramebuffers;
-    nsRefPtr<WebGLFramebuffer> mBoundDepthFramebuffer;
-    nsRefPtr<WebGLFramebuffer> mBoundStencilFramebuffer;
+    // XXX these 3 are wrong types, and aren't used atm (except for the length of the attachments)
+    nsTArray<WebGLObjectRefPtr<WebGLTexture> > mFramebufferColorAttachments;
+    nsRefPtr<WebGLFramebuffer> mFramebufferDepthAttachment;
+    nsRefPtr<WebGLFramebuffer> mFramebufferStencilAttachment;
 
+    nsRefPtr<WebGLFramebuffer> mBoundFramebuffer;
     nsRefPtr<WebGLRenderbuffer> mBoundRenderbuffer;
 
     // lookup tables for GL name -> object wrapper
     nsRefPtrHashtable<nsUint32HashKey, WebGLTexture> mMapTextures;
     nsRefPtrHashtable<nsUint32HashKey, WebGLBuffer> mMapBuffers;
     nsRefPtrHashtable<nsUint32HashKey, WebGLProgram> mMapPrograms;
     nsRefPtrHashtable<nsUint32HashKey, WebGLShader> mMapShaders;
     nsRefPtrHashtable<nsUint32HashKey, WebGLFramebuffer> mMapFramebuffers;
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -377,67 +377,62 @@ WebGLContext::BindBuffer(GLenum target, 
 {
     WebGLBuffer *wbuf = static_cast<WebGLBuffer*>(buffer);
 
     if (wbuf && wbuf->Deleted())
         return ErrorMessage("glBindBuffer: buffer has already been deleted!");
 
     MakeContextCurrent();
 
+    //printf ("BindBuffer0: %04x\n", gl->fGetError());
+
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         mBoundArrayBuffer = wbuf;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         mBoundElementArrayBuffer = wbuf;
     } else {
         return ErrorMessage("glBindBuffer: invalid target!");
     }
 
     gl->fBindBuffer(target, wbuf ? wbuf->GLName() : 0);
 
+    //printf ("BindBuffer: %04x\n", gl->fGetError());
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindFramebuffer(GLenum target, nsIWebGLFramebuffer *fb)
 {
     WebGLFramebuffer *wfb = static_cast<WebGLFramebuffer*>(fb);
 
     if (wfb && wfb->Deleted())
         return ErrorMessage("glBindFramebuffer: framebuffer has already been deleted!");
 
     MakeContextCurrent();
 
-    if (target >= LOCAL_GL_COLOR_ATTACHMENT0 &&
-        target < (LOCAL_GL_COLOR_ATTACHMENT0 + mBoundColorFramebuffers.Length()))
-    {
-        int targetOffset = target - LOCAL_GL_COLOR_ATTACHMENT0;
-        mBoundColorFramebuffers[targetOffset] = wfb;
-    } else if (target == LOCAL_GL_DEPTH_ATTACHMENT) {
-        mBoundDepthFramebuffer = wfb;
-    } else if (target == LOCAL_GL_STENCIL_ATTACHMENT) {
-        mBoundStencilFramebuffer = wfb;
-    } else {
-        return ErrorMessage("glBindFramebuffer: invalid target");
+    if (target != LOCAL_GL_FRAMEBUFFER) {
+        return ErrorMessage("glBindFramebuffer: target must be GL_FRAMEBUFFER");
     }
 
     gl->fBindFramebuffer(target, wfb ? wfb->GLName() : 0);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindRenderbuffer(GLenum target, nsIWebGLRenderbuffer *rb)
 {
     WebGLRenderbuffer *wrb = static_cast<WebGLRenderbuffer*>(rb);
 
     if (wrb && wrb->Deleted())
         return ErrorMessage("glBindRenderbuffer: renderbuffer has already been deleted!");
 
     if (target != LOCAL_GL_RENDERBUFFER)
-        return ErrorMessage("glBindRenderbuffer: invalid target");
+        return ErrorMessage("glBindRenderbuffer: target must be GL_RENDERBUFFER");
 
     MakeContextCurrent();
 
     gl->fBindRenderbuffer(target,