Bug 534527 - Accessibility needs new DOM API, r=olli.pettay, sr=roc
authorAlexander Surkov <surkov.alexander@gmail.com>
Fri, 12 Feb 2010 01:34:01 +0800
changeset 38069 a0d63d34b3ae97c6cae7f42bf4e46dcb5d155d92
parent 38068 f3ebaefe79b207542d636ba30e132ee94084267a
child 38070 fe08cc55524896c2d51697c1f7fdb7d7d5bab0b6
push idunknown
push userunknown
push dateunknown
reviewersolli.pettay, roc
bugs534527
milestone1.9.3a2pre
Bug 534527 - Accessibility needs new DOM API, r=olli.pettay, sr=roc
content/base/public/nsIContent.h
content/base/src/nsContentList.h
content/base/src/nsGenericDOMDataNode.cpp
content/base/src/nsGenericDOMDataNode.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/svg/content/src/nsSVGUseElement.h
content/xbl/src/nsBindingManager.cpp
content/xbl/src/nsBindingManager.h
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsComboboxControlFrame.h
layout/forms/nsFileControlFrame.cpp
layout/forms/nsFileControlFrame.h
layout/forms/nsGfxButtonControlFrame.cpp
layout/forms/nsGfxButtonControlFrame.h
layout/forms/nsIsIndexFrame.cpp
layout/forms/nsIsIndexFrame.h
layout/forms/nsTextControlFrame.cpp
layout/forms/nsTextControlFrame.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIAnonymousContentCreator.h
layout/generic/nsVideoFrame.cpp
layout/generic/nsVideoFrame.h
layout/svg/base/src/nsSVGUseFrame.cpp
layout/xul/base/src/nsDocElementBoxFrame.cpp
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -147,16 +147,40 @@ public:
    * Get the document for this content.
    * @return the document
    */
   nsIDocument *GetDocument() const
   {
     return GetCurrentDoc();
   }
 
+  enum {
+    /**
+     * All children will be returned.
+     *
+     * @note the result children order is
+     *   1. :before generated contnent
+     *   2. explicit children and XBL anonymous children
+     *   3. native anonymous content
+     *   4. :after generated content
+     */
+    eAllChildren = 0,
+
+    /**
+     * All children but XBL anonymous children will be returned.
+     */
+    eAllButXBL = 1
+  };
+
+  /**
+   * Return children of the node, including explict, native anonymous, XBL
+   * anonymous and genererated nodes until the child type is given (see above).
+   */
+  virtual already_AddRefed<nsINodeList> GetChildren(PRInt32 aChildType) = 0;
+
   /**
    * Get whether this content is C++-generated anonymous content
    * @see nsIAnonymousContentCreator
    * @return whether this content is anonymous
    */
   PRBool IsRootOfNativeAnonymousSubtree() const
   {
     NS_ASSERTION(!HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT) ||
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -92,16 +92,21 @@ public:
   
   PRUint32 Length() const { 
     return mElements.Count();
   }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsBaseContentList, nsINodeList)
 
   void AppendElement(nsIContent *aContent);
+  void MaybeAppendElement(nsIContent* aContent)
+  {
+    if (aContent)
+      AppendElement(aContent);
+  }
 
   /**
    * Insert the element at a given index, shifting the objects at
    * the given index and later to make space.
    * @param aContent Element to insert, must not be null
    * @param aIndex Index to insert the element at.
    */
   void InsertElementAt(nsIContent* aContent, PRInt32 aIndex);
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -614,16 +614,22 @@ nsGenericDOMDataNode::UnbindFromTree(PRB
   nsDataSlots *slots = GetExistingDataSlots();
   if (slots) {
     slots->mBindingParent = nsnull;
   }
 
   nsNodeUtils::ParentChainChanged(this);
 }
 
+already_AddRefed<nsINodeList>
+nsGenericDOMDataNode::GetChildren(PRInt32 aChildType)
+{
+  return nsnull;
+}
+
 nsIAtom *
 nsGenericDOMDataNode::GetIDAttributeName() const
 {
   return nsnull;
 }
 
 already_AddRefed<nsINodeInfo>
 nsGenericDOMDataNode::GetExistingAttrNameFromQName(const nsAString& aStr) const
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -195,16 +195,18 @@ public:
 
   // Implementation for nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
 
+  virtual already_AddRefed<nsINodeList> GetChildren(PRInt32 aChildType);
+
   virtual nsIAtom *GetIDAttributeName() const;
   virtual already_AddRefed<nsINodeInfo> GetExistingAttrNameFromQName(const nsAString& aStr) const;
   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, PRBool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -55,16 +55,17 @@
 #include "nsIContentIterator.h"
 #include "nsIEventListenerManager.h"
 #include "nsFocusManager.h"
 #include "nsILinkHandler.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsIFrame.h"
+#include "nsIAnonymousContentCreator.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsStyleConsts.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsIEventStateManager.h"
 #include "nsIDOMEvent.h"
 #include "nsIPrivateDOMEvent.h"
@@ -2691,16 +2692,90 @@ nsGenericElement::UnbindFromTree(PRBool 
       // parent, though, since this only walks non-anonymous kids.
       mAttrsAndChildren.ChildAt(i)->UnbindFromTree(PR_TRUE, PR_FALSE);
     }
   }
 
   nsNodeUtils::ParentChainChanged(this);
 }
 
+already_AddRefed<nsINodeList>
+nsGenericElement::GetChildren(PRInt32 aChildType)
+{
+  nsRefPtr<nsBaseContentList> list = new nsBaseContentList();
+  if (!list) {
+    return nsnull;
+  }
+
+  nsIFrame *frame = GetPrimaryFrame();
+
+  // Append :before generated content.
+  if (frame) {
+    nsIFrame *beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
+    if (beforeFrame) {
+      nsIContent* beforeContent = beforeFrame->GetContent();
+      if (beforeFrame) {
+        list->AppendElement(beforeContent);
+      }
+    }
+  }
+
+  // If XBL is bound to this node then append XBL anonymous content including
+  // explict content altered by insertion point if we were requested for XBL
+  // anonymous content, otherwise append explicit content with respect to
+  // insertion point if any.
+  nsINodeList *childList = nsnull;
+
+  nsIDocument* document = GetOwnerDoc();
+  if (document) {
+    if (aChildType != eAllButXBL) {
+      childList = document->BindingManager()->GetXBLChildNodesFor(this);
+      if (!childList) {
+        childList = GetChildNodesList();
+      }
+
+    } else {
+      childList = document->BindingManager()->GetContentListFor(this);
+    }
+  } else {
+    childList = GetChildNodesList();
+  }
+
+  if (childList) {
+    PRUint32 length = 0;
+    childList->GetLength(&length);
+    for (PRUint32 idx = 0; idx < length; idx++) {
+      nsIContent* child = childList->GetNodeAt(idx);
+      list->AppendElement(child);
+    }
+  }
+
+  if (frame) {
+    // Append native anonymous content to the end.
+    nsIAnonymousContentCreator* creator = do_QueryFrame(frame);
+    if (creator) {
+      creator->GetAnonymousContent(*list);
+    }
+
+    // Append :after generated content.
+    nsIFrame *afterFrame = nsLayoutUtils::GetAfterFrame(frame);
+    if (afterFrame) {
+      nsIContent* afterContent = afterFrame->GetContent();
+      if (afterFrame) {
+        list->AppendElement(afterContent);
+      }
+    }
+  }
+
+  nsINodeList* returnList = nsnull;
+  list.forget(&returnList);
+  return returnList;
+}
+
+
 nsresult
 nsGenericElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   return nsGenericElement::doPreHandleEvent(this, aVisitor);
 }
 
 static nsIContent*
 FindNativeAnonymousSubtreeOwner(nsIContent* aContent)
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -373,16 +373,17 @@ public:
   }
 
   // nsIContent interface methods
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
+  virtual already_AddRefed<nsINodeList> GetChildren(PRInt32 aChildType);
   virtual nsIAtom *GetIDAttributeName() const;
   virtual nsIAtom *GetClassAttributeName() const;
   virtual already_AddRefed<nsINodeInfo> GetExistingAttrNameFromQName(const nsAString& aStr) const;
   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, PRBool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
   }
--- a/content/svg/content/src/nsSVGUseElement.h
+++ b/content/svg/content/src/nsSVGUseElement.h
@@ -91,16 +91,17 @@ public:
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGUseElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGUseElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGUseElementBase::)
 
   // for nsSVGUseFrame's nsIAnonymousContentCreator implementation.
   nsIContent* CreateAnonymousContent();
+  nsIContent* GetAnonymousContent() const { return mClone; }
   void DestroyAnonymousContent();
 
   // nsSVGElement specializations:
   virtual gfxMatrix PrependLocalTransformTo(const gfxMatrix &aMatrix);
   virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeString(PRUint8 aAttrEnum);
 
   // nsIContent interface
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -678,31 +678,36 @@ nsBindingManager::ResolveTag(nsIContent*
   }
 
   *aNameSpaceID = aContent->GetNameSpaceID();
   return aContent->Tag();
 }
 
 nsresult
 nsBindingManager::GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult)
+{
+  NS_IF_ADDREF(*aResult = GetContentListFor(aContent));
+  return NS_OK;
+}
+
+nsINodeList*
+nsBindingManager::GetContentListFor(nsIContent* aContent)
 { 
-  *aResult = nsnull;
-  
+  nsINodeList* result = nsnull;
+
   if (mContentListTable.ops) {
-    *aResult = static_cast<nsAnonymousContentList*>
-                          (LookupObject(mContentListTable, aContent));
-    NS_IF_ADDREF(*aResult);
-  }
-  
-  if (!*aResult) {
-    nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aContent));
-    node->GetChildNodes(aResult);
+    result = static_cast<nsAnonymousContentList*>
+      (LookupObject(mContentListTable, aContent));
   }
 
-  return NS_OK;
+  if (!result) {
+    result = aContent->GetChildNodesList();
+  }
+
+  return result;
 }
 
 nsresult
 nsBindingManager::SetContentListFor(nsIContent* aContent,
                                     nsInsertionPointList* aList)
 {
   if (mDestroyed) {
     return NS_OK;
--- a/content/xbl/src/nsBindingManager.h
+++ b/content/xbl/src/nsBindingManager.h
@@ -104,16 +104,21 @@ public:
 
   /**
    * Return a list of all explicit children, including any children
    * that may have been inserted via XBL insertion points.
    */
   nsresult GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult);
 
   /**
+   * Non-COMy version of GetContentListFor.
+   */
+  nsINodeList* GetContentListFor(nsIContent* aContent);
+
+  /**
    * Set the insertion point children for the specified element.
    * The binding manager assumes ownership of aList.
    */
   nsresult SetContentListFor(nsIContent* aContent,
                              nsInsertionPointList* aList);
 
   /**
    * Determine whether or not the explicit child list has been altered
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -1037,16 +1037,23 @@ nsComboboxControlFrame::CreateAnonymousC
                           NS_LITERAL_STRING("-1"), PR_FALSE);
 
   if (!aElements.AppendElement(mButtonContent))
     return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
+void
+nsComboboxControlFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  aElements.MaybeAppendElement(mDisplayContent);
+  aElements.MaybeAppendElement(mButtonContent);
+}
+
 // XXXbz this is a for-now hack.  Now that display:inline-block works,
 // need to revisit this.
 class nsComboboxDisplayFrame : public nsBlockFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsComboboxDisplayFrame (nsStyleContext* aContext,
                           nsComboboxControlFrame* aComboBox)
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -94,16 +94,17 @@ public:
   nsComboboxControlFrame(nsStyleContext* aContext);
   ~nsComboboxControlFrame();
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
   virtual nsIFrame* CreateFrameFor(nsIContent* aContent);
 
 #ifdef ACCESSIBILITY
   NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
 #endif
 
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
 
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -94,20 +94,20 @@
 #define SYNC_TEXT 0x1
 #define SYNC_BUTTON 0x2
 #define SYNC_BOTH 0x3
 
 #define CPS_PREF_NAME NS_LITERAL_STRING("browser.upload.lastDir")
 
 class UploadLastDir : public nsIObserver, public nsSupportsWeakReference {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
-
-  UploadLastDir();
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  UploadLastDir();
 
   /**
    * Fetch the last used directory for this location from the content
    * pref service, if it is available.
    *
    * @param aURI URI of the current page
    * @param aFile path to the last used directory
    */
@@ -122,17 +122,17 @@ public:
    */
   nsresult StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile);
 private:
   // Directories are stored here during private browsing mode
   nsInterfaceHashtable<nsStringHashKey, nsILocalFile> mUploadLastDirStore;
   PRBool mInPrivateBrowsing;
 };
 
-NS_IMPL_ISUPPORTS2(UploadLastDir, nsIObserver, nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS2(UploadLastDir, nsIObserver, nsISupportsWeakReference)
 UploadLastDir* gUploadLastDir = nsnull;
 
 nsIFrame*
 NS_NewFileControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsFileControlFrame(aContext);
 }
 
@@ -281,16 +281,23 @@ nsFileControlFrame::CreateAnonymousConte
                                       systemGroup);
 
   SyncAttr(kNameSpaceID_None, nsGkAtoms::size,     SYNC_TEXT);
   SyncAttr(kNameSpaceID_None, nsGkAtoms::disabled, SYNC_BOTH);
 
   return NS_OK;
 }
 
+void
+nsFileControlFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  aElements.MaybeAppendElement(mTextContent);
+  aElements.MaybeAppendElement(mBrowse);
+}
+
 NS_QUERYFRAME_HEAD(nsFileControlFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
   NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
 
 void 
 nsFileControlFrame::SetFocus(PRBool aOn, PRBool aRepaint)
 {
@@ -492,21 +499,21 @@ void nsFileControlFrame::InitUploadLastD
 
 void nsFileControlFrame::DestroyUploadLastDir() {
   NS_RELEASE(gUploadLastDir);
 }
 
 UploadLastDir::UploadLastDir():
   mInPrivateBrowsing(PR_FALSE)
 {
-  nsCOMPtr<nsIPrivateBrowsingService> pbService =
-    do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
-  if (pbService) {
-    pbService->GetPrivateBrowsingEnabled(&mInPrivateBrowsing);
-  }
+  nsCOMPtr<nsIPrivateBrowsingService> pbService =
+    do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
+  if (pbService) {
+    pbService->GetPrivateBrowsingEnabled(&mInPrivateBrowsing);
+  }
 
   mUploadLastDirStore.Init();
 }
 
 nsresult
 UploadLastDir::FetchLastUsedDirectory(nsIURI* aURI, nsILocalFile** aFile)
 {
   NS_PRECONDITION(aURI, "aURI is null");
@@ -539,23 +546,23 @@ UploadLastDir::FetchLastUsedDirectory(ns
   // Get the last used directory, if it is stored
   PRBool hasPref;
   if (NS_SUCCEEDED(contentPrefService->HasPref(uri, CPS_PREF_NAME, &hasPref)) && hasPref) {
     nsCOMPtr<nsIVariant> pref;
     contentPrefService->GetPref(uri, CPS_PREF_NAME, nsnull, getter_AddRefs(pref));
     nsString prefStr;
     pref->GetAsAString(prefStr);
 
-    nsCOMPtr<nsILocalFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
-    if (!localFile)
-      return NS_ERROR_OUT_OF_MEMORY;
-    localFile->InitWithPath(prefStr);
-
+    nsCOMPtr<nsILocalFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+    if (!localFile)
+      return NS_ERROR_OUT_OF_MEMORY;
+    localFile->InitWithPath(prefStr);
+
     *aFile = localFile;
-    NS_ADDREF(*aFile);
+    NS_ADDREF(*aFile);
   }
   return NS_OK;
 }
 
 nsresult
 UploadLastDir::StoreLastUsedDirectory(nsIURI* aURI, nsILocalFile* aFile)
 {
   NS_PRECONDITION(aURI, "aURI is null");
@@ -593,19 +600,19 @@ UploadLastDir::StoreLastUsedDirectory(ns
     return NS_OK;
   nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
   if (!prefValue)
     return NS_ERROR_OUT_OF_MEMORY;
   prefValue->SetAsAString(unicodePath);
   return contentPrefService->SetPref(uri, CPS_PREF_NAME, prefValue);
 }
 
-NS_IMETHODIMP
-UploadLastDir::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
-{
+NS_IMETHODIMP
+UploadLastDir::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
+{
   if (strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
     if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(aData)) {
       mInPrivateBrowsing = PR_TRUE;
     } else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
       mInPrivateBrowsing = PR_FALSE;
       if (mUploadLastDirStore.IsInitialized()) {
         mUploadLastDirStore.Clear();
       }
--- a/layout/forms/nsFileControlFrame.h
+++ b/layout/forms/nsFileControlFrame.h
@@ -88,16 +88,17 @@ public:
                               nsIAtom*        aAttribute,
                               PRInt32         aModType);
   virtual PRBool IsLeaf() const;
 
 
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
 
 #ifdef ACCESSIBILITY
   NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
 #endif
 
   // create and destroy the static UploadLastDir object for remembering
   // which directory was last used on a site-by-site basis
   static void InitUploadLastDir();
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -126,16 +126,22 @@ nsGfxButtonControlFrame::CreateAnonymous
 
   // set the value of the text node and add it to the child list
   mTextContent->SetText(label, PR_FALSE);
   if (!aElements.AppendElement(mTextContent))
     return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
+void
+nsGfxButtonControlFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  aElements.MaybeAppendElement(mTextContent);
+}
+
 // Create the text content used as label for the button.
 // The frame will be generated by the frame constructor.
 nsIFrame*
 nsGfxButtonControlFrame::CreateFrameFor(nsIContent*      aContent)
 {
   nsIFrame * newFrame = nsnull;
 
   if (aContent == mTextContent) {
--- a/layout/forms/nsGfxButtonControlFrame.h
+++ b/layout/forms/nsGfxButtonControlFrame.h
@@ -76,16 +76,17 @@ public:
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   NS_DECL_QUERYFRAME
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
   virtual nsIFrame* CreateFrameFor(nsIContent* aContent);
 
   // nsIFormControlFrame
   virtual nsresult GetFormProperty(nsIAtom* aName, nsAString& aValue) const; 
 
 
   NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
                               nsIAtom*        aAttribute,
--- a/layout/forms/nsIsIndexFrame.cpp
+++ b/layout/forms/nsIsIndexFrame.cpp
@@ -233,16 +233,23 @@ nsIsIndexFrame::CreateAnonymousContent(n
   // Create an hr
   NS_NewHTMLElement(getter_AddRefs(mPostHr), hrInfo, PR_FALSE);
   if (!mPostHr || !aElements.AppendElement(mPostHr))
     return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
+void
+nsIsIndexFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  aElements.MaybeAppendElement(mTextContent);
+  aElements.MaybeAppendElement(mInputContent);
+}
+
 NS_QUERYFRAME_HEAD(nsIsIndexFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
   NS_QUERYFRAME_ENTRY(nsIStatefulFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
 
 NS_IMPL_ISUPPORTS2(nsIsIndexFrame::KeyListener,
                    nsIDOMKeyListener,
                    nsIDOMEventListener)
--- a/layout/forms/nsIsIndexFrame.h
+++ b/layout/forms/nsIsIndexFrame.h
@@ -93,16 +93,17 @@ public:
   NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
                               nsIAtom*        aAttribute,
                               PRInt32         aModType);
 
   void           SetFocus(PRBool aOn, PRBool aRepaint);
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
 
   NS_IMETHOD OnSubmit(nsPresContext* aPresContext);
 
   //nsIStatefulFrame
   NS_IMETHOD SaveState(SpecialStateID aStateID, nsPresState** aState);
   NS_IMETHOD RestoreState(nsPresState* aState);
 
 protected:
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -1665,16 +1665,22 @@ nsTextControlFrame::CreateAnonymousConte
 
   if (!nsContentUtils::AddScriptRunner(new EditorInitializer(this))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return NS_OK;
 }
 
+void
+nsTextControlFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  aElements.MaybeAppendElement(mAnonymousDiv);
+}
+
 nscoord
 nsTextControlFrame::GetMinWidth(nsIRenderingContext* aRenderingContext)
 {
   // Our min width is just our preferred width if we have auto width.
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
 
   result = GetPrefWidth(aRenderingContext);
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -134,16 +134,17 @@ public:
     // nsStackFrame is already both of these, but that's somewhat bogus,
     // and we really mean it.
     return nsStackFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
 
   // Utility methods to set current widget state
 
   // Be careful when using this method.
   // Calling it may cause |this| to be deleted.
   // In that case the method returns an error value.
   nsresult SetValue(const nsAString& aValue);
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -101,16 +101,22 @@ nsHTMLScrollFrame::nsHTMLScrollFrame(nsI
 
 nsresult
 nsHTMLScrollFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
 {
   return mInner.CreateAnonymousContent(aElements);
 }
 
 void
+nsHTMLScrollFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  mInner.GetAnonymousContent(aElements);
+}
+
+void
 nsHTMLScrollFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   mInner.Destroy();
   nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsHTMLScrollFrame::SetInitialChildList(nsIAtom*     aListName,
@@ -949,16 +955,22 @@ nsMargin nsGfxScrollFrameInner::GetDesir
 
 nsresult
 nsXULScrollFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
 {
   return mInner.CreateAnonymousContent(aElements);
 }
 
 void
+nsXULScrollFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  mInner.GetAnonymousContent(aElements);
+}
+
+void
 nsXULScrollFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   mInner.Destroy();
   nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsXULScrollFrame::SetInitialChildList(nsIAtom*        aListName,
@@ -2234,16 +2246,24 @@ nsGfxScrollFrameInner::CreateAnonymousCo
     if (!aElements.AppendElement(mScrollCornerContent))
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return NS_OK;
 }
 
 void
+nsGfxScrollFrameInner::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  aElements.MaybeAppendElement(mHScrollbarContent);
+  aElements.MaybeAppendElement(mVScrollbarContent);
+  aElements.MaybeAppendElement(mScrollCornerContent);
+}
+
+void
 nsGfxScrollFrameInner::Destroy()
 {
   // Unbind any content created in CreateAnonymousContent from the tree
   nsContentUtils::DestroyAnonymousContent(&mHScrollbarContent);
   nsContentUtils::DestroyAnonymousContent(&mVScrollbarContent);
   nsContentUtils::DestroyAnonymousContent(&mScrollCornerContent);
 
   if (mPostedReflowCallback) {
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -76,16 +76,17 @@ public:
   ScrollbarStyles GetScrollbarStylesFromFrame() const;
 
   // If a child frame was added or removed on the scrollframe,
   // reload our child frame list.
   // We need this if a scrollbar frame is recreated.
   void ReloadChildFrames();
 
   nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  void GetAnonymousContent(nsBaseContentList& aElements);
   nsresult FireScrollPortEvent();
   void PostOverflowEvent();
   void Destroy();
 
   nsresult BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                             const nsRect&           aDirtyRect,
                             const nsDisplayListSet& aLists);
 
@@ -367,16 +368,17 @@ public:
   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
   { nsPoint pt = aChild->GetPosition();
     if (aChild == mInner.GetScrolledFrame()) pt += GetScrollPosition();
     return pt;
   }
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
 
   // nsIScrollableFrame
   virtual nsIFrame* GetScrolledFrame() const {
     return mInner.GetScrolledFrame();
   }
   virtual nsGfxScrollFrameInner::ScrollbarStyles GetScrollbarStyles() const {
     return mInner.GetScrollbarStylesFromFrame();
   }
@@ -561,16 +563,17 @@ public:
   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
   { nsPoint pt = aChild->GetPosition();
     if (aChild == mInner.GetScrolledFrame()) pt += GetScrollPosition();
     return pt;
   }
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
 
   virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState);
   virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState);
   virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState);
   virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState);
 
   NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState);
   NS_IMETHOD GetPadding(nsMargin& aPadding);
--- a/layout/generic/nsIAnonymousContentCreator.h
+++ b/layout/generic/nsIAnonymousContentCreator.h
@@ -67,16 +67,21 @@ public:
    * @note The returned elements are owned by this object. This object is
    *       responsible for calling UnbindFromTree on the elements it returned
    *       from CreateAnonymousContent when appropriate (i.e. before releasing
    *       them).
    */
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements)=0;
 
   /**
+   * Returns "native" anonymous content created by CreateAnonymousContent().
+   */
+  virtual void GetAnonymousContent(nsBaseContentList& aElements) = 0;
+
+  /**
    * Implementations can override this method to create special frames for the
    * anonymous content returned from CreateAnonymousContent.
    * By default this method returns nsnull, which means the default frame
    * is created.
    */
   virtual nsIFrame* CreateFrameFor(nsIContent* aContent) { return nsnull; }
 };
 
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -131,16 +131,23 @@ nsVideoFrame::CreateAnonymousContent(nsT
   NS_ENSURE_SUCCESS(rv, rv);
   if (!aElements.AppendElement(mVideoControls))
     return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
 void
+nsVideoFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  aElements.MaybeAppendElement(mPosterImage);
+  aElements.MaybeAppendElement(mVideoControls);
+}
+
+void
 nsVideoFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsContentUtils::DestroyAnonymousContent(&mVideoControls);
   nsContentUtils::DestroyAnonymousContent(&mPosterImage);
   nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 PRBool
--- a/layout/generic/nsVideoFrame.h
+++ b/layout/generic/nsVideoFrame.h
@@ -95,16 +95,17 @@ public:
   virtual nsIAtom* GetType() const;
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
     return nsSplittableFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced));
   }
   
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
 
   nsIContent* GetPosterImage() { return mPosterImage; }
 
   // Returns PR_TRUE if we should display the poster. Note that once we show
   // a video frame, the poster will never be displayed again.
   PRBool ShouldDisplayPoster();
 
 #ifdef DEBUG
--- a/layout/svg/base/src/nsSVGUseFrame.cpp
+++ b/layout/svg/base/src/nsSVGUseFrame.cpp
@@ -84,16 +84,17 @@ public:
   NS_IMETHOD GetFrameName(nsAString& aResult) const
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGUse"), aResult);
   }
 #endif
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
 };
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsIFrame*
 NS_NewSVGUseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
@@ -175,8 +176,16 @@ nsSVGUseFrame::CreateAnonymousContent(ns
 
   nsIContent* clone = use->CreateAnonymousContent();
   if (!clone)
     return NS_ERROR_FAILURE;
   if (!aElements.AppendElement(clone))
     return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
+
+void
+nsSVGUseFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  nsSVGUseElement *use = static_cast<nsSVGUseElement*>(mContent);
+  nsIContent* clone = use->GetAnonymousContent();
+  aElements.MaybeAppendElement(clone);
+}
--- a/layout/xul/base/src/nsDocElementBoxFrame.cpp
+++ b/layout/xul/base/src/nsDocElementBoxFrame.cpp
@@ -71,16 +71,17 @@ public:
   nsDocElementBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext)
     :nsBoxFrame(aShell, aContext, PR_TRUE) {}
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void GetAnonymousContent(nsBaseContentList& aElements);
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
     // Override nsBoxFrame.
     if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
       return PR_FALSE;
     return nsBoxFrame::IsFrameOfType(aFlags);
   }
@@ -145,16 +146,23 @@ nsDocElementBoxFrame::CreateAnonymousCon
                            NS_LITERAL_STRING("true"), PR_FALSE);
 
   if (!aElements.AppendElement(mTooltipContent))
     return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
+void
+nsDocElementBoxFrame::GetAnonymousContent(nsBaseContentList& aElements)
+{
+  aElements.MaybeAppendElement(mPopupgroupContent);
+  aElements.MaybeAppendElement(mTooltipContent);
+}
+
 NS_QUERYFRAME_HEAD(nsDocElementBoxFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsDocElementBoxFrame::GetFrameName(nsAString& aResult) const
 {