Fix for bug 376275 - get rid an assertion from getTextAtOffset on list bullets, r=aaronlev
authorsurkov.alexander@gmail.com
Tue, 10 Apr 2007 21:17:33 -0700
changeset 460 985f22474d24c94b6cd99a868896d53c356f9825
parent 459 8a0ea9cee62d6f4959ecb12e7a248cebe17bdaf1
child 461 b22376bb9f4ac7f8834e147f252a2a3c4d692d2c
push idunknown
push userunknown
push dateunknown
reviewersaaronlev
bugs376275
milestone1.9a4pre
Fix for bug 376275 - get rid an assertion from getTextAtOffset on list bullets, r=aaronlev
accessible/public/nsPIAccessible.idl
accessible/src/base/nsAccessible.cpp
accessible/src/base/nsTextAccessible.cpp
accessible/src/base/nsTextAccessible.h
accessible/src/html/nsHTMLTextAccessible.cpp
accessible/src/html/nsHTMLTextAccessible.h
accessible/src/html/nsHyperTextAccessible.cpp
--- a/accessible/public/nsPIAccessible.idl
+++ b/accessible/public/nsPIAccessible.idl
@@ -35,31 +35,63 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 interface nsIAccessible;
 
-[scriptable, uuid(52F1BE88-84F7-4f7f-B31C-062AFE7DF15D)]
+[uuid(e4865da3-f292-4f1a-9c56-dd307f1bdc17)]
 interface nsPIAccessible : nsISupports
 {
-  [noscript] void setParent(in nsIAccessible aAccParent);
-  [noscript] void setFirstChild(in nsIAccessible aAccFirstChild);
-  [noscript] void setNextSibling(in nsIAccessible aAccNextSibling);
-  // Return parent only if cached
-  [noscript] void getCachedParent(out nsIAccessible aAccParent);
+  /**
+   * Set accessible parent.
+   */
+  void setParent(in nsIAccessible aAccParent);
+
+  /**
+   * Set first accessible child.
+   */
+  void setFirstChild(in nsIAccessible aAccFirstChild);
+
+  /**
+   * Set next sibling accessible.
+   */
+  void setNextSibling(in nsIAccessible aAccNextSibling);
+
+  /**
+   * Return parent accessible only if cached.
+   */
+  void getCachedParent(out nsIAccessible aAccParent);
 
   /**
    * Set the child count to -1 (unknown) and null out cached child pointers
    */
-  [noscript] void invalidateChildren();
-  [noscript] void fireToolkitEvent(in unsigned long aEvent, in nsIAccessible aTarget, in voidPtr aData);
+  void invalidateChildren();
+
+  /**
+   * Fire accessible event.
+   *
+   * @param aEvent - DOM event
+   * @param aTarget - target of DOM event
+   * @param aData - additional information for accessible event.
+   */
+  void fireToolkitEvent(in unsigned long aEvent, in nsIAccessible aTarget,
+                        in voidPtr aData);
 
   /**
    * Return true if there are accessible children in anonymous content
    */
-  [noscript] readonly attribute boolean allowsAnonChildAccessibles;
+  readonly attribute boolean allowsAnonChildAccessibles;
 
-  [noscript] void testChildCache(in nsIAccessible aCachedChild); // Assert if child not in parent's cache
+  /**
+   * Assert if child not in parent's cache.
+   */
+  void testChildCache(in nsIAccessible aCachedChild);
+
+  /**
+   * Returns text of accessible if accessible has text role otherwise empty
+   * string.
+   */
+  AString getContentText();
 };
 
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -3121,35 +3121,32 @@ nsresult nsAccessible::GetLinkOffset(PRI
     accessible.swap(nextSibling);
   }
 
   return NS_ERROR_FAILURE;
 }
 
 PRInt32 nsAccessible::TextLength(nsIAccessible *aAccessible)
 {
-  if (!IsText(aAccessible)) {
+  if (!IsText(aAccessible))
     return 1;
-  }
-  nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(aAccessible));
-  nsIFrame *frame = accessNode->GetFrame();
-  if (!frame) {
-    return 0;
-  }
-  PRInt32 textLength = frame->GetContent()->TextLength();
-  if (!textLength) {
-    // This is exception to the frame owns the text.
-    // The only known case where this occurs is for list bullets
-    // We could do this for all accessibles but it's not as performant
-    // as dealing with nsIContent directly
-    nsAutoString childText;
-    aAccessible->GetName(childText);
-    textLength = childText.Length();
-  }
-  return textLength;
+
+  nsCOMPtr<nsPIAccessible> pAcc(do_QueryInterface(aAccessible));
+  NS_ENSURE_TRUE(pAcc, NS_ERROR_FAILURE);
+
+  nsAutoString text;
+  pAcc->GetContentText(text);
+  return text.Length();
+}
+
+NS_IMETHODIMP
+nsAccessible::GetContentText(nsAString& aText)
+{
+  aText.Truncate();
+  return NS_OK;
 }
 
 already_AddRefed<nsIAccessible>
 nsAccessible::GetFirstAvailableAccessible(nsIDOMNode *aStartNode, PRBool aRequireLeaf)
 {
   nsIAccessibilityService *accService = GetAccService();
   nsCOMPtr<nsIAccessible> accessible;
   nsCOMPtr<nsIDOMTreeWalker> walker; 
--- a/accessible/src/base/nsTextAccessible.cpp
+++ b/accessible/src/base/nsTextAccessible.cpp
@@ -83,8 +83,22 @@ NS_IMETHODIMP nsTextAccessible::GetLastC
   * No Children
   */
 NS_IMETHODIMP nsTextAccessible::GetChildCount(PRInt32 *_retval)
 {
   *_retval = 0;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsTextAccessible::GetContentText(nsAString& aText)
+{
+  nsresult rv = nsLinkableAccessible::GetContentText(aText);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsIFrame *frame = GetFrame();
+  if (!frame)
+    return NS_OK;
+
+  frame->GetContent()->AppendTextTo(aText);
+  return NS_OK;
+}
+
--- a/accessible/src/base/nsTextAccessible.h
+++ b/accessible/src/base/nsTextAccessible.h
@@ -47,17 +47,22 @@
   *  this way.
   */
 class nsTextAccessible : public nsLinkableAccessible
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   nsTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
+
+  // nsIAccessible
   NS_IMETHOD GetRole(PRUint32 *_retval); 
   NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
   NS_IMETHOD GetLastChild(nsIAccessible **_retval);
   NS_IMETHOD GetChildCount(PRInt32 *_retval);
+
+  // nsPIAccessible
+  NS_IMETHOD GetContentText(nsAString& aText);
 };
 
 
 #endif
 
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -395,16 +395,23 @@ nsHTMLListBulletAccessible::FireToolkitE
                                              nsIAccessible *aTarget,
                                              void *aData)
 {
   if (aEvent == nsIAccessibleEvent::EVENT_HIDE)
     mFrame = nsnull;  // Invalidate cached frame
   return nsLeafAccessible::FireToolkitEvent(aEvent, aTarget, aData);
 }
 
+NS_IMETHODIMP
+nsHTMLListBulletAccessible::GetContentText(nsAString& aText)
+{
+  aText = mBulletText;
+  return NS_OK;
+}
+
 
 // nsHTMLListAccessible
 
 NS_IMETHODIMP
 nsHTMLListAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
 {
   nsresult rv = nsHyperTextAccessible::GetState(aState, aExtraState);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/accessible/src/html/nsHTMLTextAccessible.h
+++ b/accessible/src/html/nsHTMLTextAccessible.h
@@ -122,16 +122,17 @@ public:
   // this LI accessible. Also, don't cache via mParent/SetParent(), prevent
   // circular reference since li holds onto us.
   NS_IMETHOD SetParent(nsIAccessible *aParentAccessible);
   NS_IMETHOD GetParent(nsIAccessible **aParentAccessible);
 
   // nsPIAccessible
   NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible *aTarget,
                               void *aData);
+  NS_IMETHOD GetContentText(nsAString& aText);
 
 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.
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -332,35 +332,27 @@ nsIFrame* nsHyperTextAccessible::GetPosA
   // depending on what we need for out parameters
   while (NextChild(accessible)) {
     nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(accessible));
     nsIFrame *frame = accessNode->GetFrame();
     if (!frame) {
       continue;
     }
     if (IsText(accessible)) {
-      // Avoid string copies
-      PRInt32 substringEndOffset = frame->GetContent()->TextLength();
+      nsCOMPtr<nsPIAccessible> pAcc(do_QueryInterface(accessible));
       nsAutoString newText;
-      if (!substringEndOffset) {
-        // This is exception to the frame owns the text.
-        // The only known case where this occurs is for list bullets
-        // We could do this for all accessibles but it's not as performant
-        // as dealing with nsIContent directly
-        accessible->GetName(newText);
-        substringEndOffset = newText.Length();
-      }
+      pAcc->GetContentText(newText);
+
+      PRInt32 substringEndOffset = newText.Length();
       if (startOffset < substringEndOffset) {
         // Our start is within this substring
         // XXX Can we somehow optimize further by getting the nsTextFragment
         // and use CopyTo to a PRUnichar buffer to copy it directly to
         // the string?
-        if (newText.IsEmpty()) { // Don't have text yet
-          frame->GetContent()->AppendTextTo(newText);
-        }
+
         if (startOffset > 0 || endOffset < substringEndOffset) {
           // XXX the Substring operation is efficient, but does the 
           // reassignment to the original nsAutoString cause a copy?
           PRInt32 outStartLineUnused;
           frame->GetChildFrameContainingOffset(startOffset, PR_TRUE, &outStartLineUnused, &frame);
           if (endOffset < substringEndOffset) {
             // Don't take entire substring: stop before the end
             substringEndOffset = endOffset;