Bug 397112. Crash [@ nsAccessible::GetFirstChild] moving text out of an option. Patch by Alexander Surkov and Mats Palmgren. r=aaronlev

This commit is contained in:
aaronleventhal%moonset.net 2007-09-28 20:55:46 +00:00
Родитель 04762f216f
Коммит 0872c250cc
3 изменённых файлов: 50 добавлений и 8 удалений

Просмотреть файл

@ -41,7 +41,7 @@
interface nsIAccessible;
interface nsIAccessibleEvent;
[uuid(03932812-53d1-4dc7-965d-6b6ad8a872b1)]
[uuid(af05f83c-6fd2-48c1-b1c3-811857472421)]
interface nsPIAccessible : nsISupports
{
/**
@ -64,6 +64,11 @@ interface nsPIAccessible : nsISupports
*/
void getCachedParent(out nsIAccessible aAccParent);
/**
* Return first child accessible only if cached.
*/
void getCachedFirstChild(out nsIAccessible aAccFirstChild);
/**
* Set the child count to -1 (unknown) and null out cached child pointers
*/

Просмотреть файл

@ -444,6 +444,16 @@ nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
NS_IMETHODIMP nsAccessible::SetParent(nsIAccessible *aParent)
{
#ifdef DEBUG
if (aParent && aParent != mParent) {
nsCOMPtr<nsPIAccessible> privParent = do_QueryInterface(mParent);
if (privParent) {
nsCOMPtr<nsIAccessible> firstChild;
privParent->GetCachedFirstChild(getter_AddRefs(firstChild));
NS_ASSERTION(firstChild != this, "Reparenting other node's first child!");
}
}
#endif
mParent = aParent;
return NS_OK;
}
@ -588,6 +598,17 @@ NS_IMETHODIMP nsAccessible::GetCachedParent(nsIAccessible ** aParent)
return NS_OK;
}
NS_IMETHODIMP nsAccessible::GetCachedFirstChild(nsIAccessible ** aFirstChild)
{
*aFirstChild = nsnull;
if (!mWeakShell) {
// This node has been shut down
return NS_ERROR_FAILURE;
}
NS_IF_ADDREF(*aFirstChild = mFirstChild);
return NS_OK;
}
/* readonly attribute nsIAccessible nextSibling; */
NS_IMETHODIMP nsAccessible::GetNextSibling(nsIAccessible * *aNextSibling)
{
@ -655,6 +676,16 @@ NS_IMETHODIMP nsAccessible::GetFirstChild(nsIAccessible * *aFirstChild)
PRInt32 numChildren;
GetChildCount(&numChildren); // Make sure we cache all of the children
#ifdef DEBUG
nsCOMPtr<nsPIAccessible> firstChild(do_QueryInterface(mFirstChild));
if (firstChild) {
nsCOMPtr<nsIAccessible> realParent;
firstChild->GetCachedParent(getter_AddRefs(realParent));
NS_ASSERTION(!realParent || realParent == this,
"Two accessibles have the same first child accessible.");
}
#endif
NS_IF_ADDREF(*aFirstChild = mFirstChild);
return NS_OK;

Просмотреть файл

@ -1549,6 +1549,15 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
accessibleEvent->GetEventType(&eventType);
if (eventType == nsIAccessibleEvent::EVENT_DOM_CREATE ||
eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) {
nsCOMPtr<nsIAccessible> containerAccessible;
if (accessible) {
accessible->GetParent(getter_AddRefs(containerAccessible));
nsCOMPtr<nsPIAccessible> privateContainerAccessible =
do_QueryInterface(containerAccessible);
if (privateContainerAccessible)
privateContainerAccessible->InvalidateChildren();
}
// Also fire text changes if the node being created could affect the text in an nsIAccessibleText parent.
// When a node is being made visible or is inserted, the text in an ancestor hyper text will gain characters
// At this point we now have the frame and accessible for this node if there is one. That is why we
@ -1557,8 +1566,10 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
nsCOMPtr<nsIDOMNode> domNode;
accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
if (domNode && domNode != mDOMNode) {
nsCOMPtr<nsIAccessible> containerAccessible;
GetAccessibleInParentChain(domNode, getter_AddRefs(containerAccessible));
if (!containerAccessible)
GetAccessibleInParentChain(domNode,
getter_AddRefs(containerAccessible));
nsCOMPtr<nsIAccessibleTextChangeEvent> textChangeEvent =
CreateTextChangeEventForNode(containerAccessible, domNode, accessible, PR_TRUE, PR_TRUE);
if (textChangeEvent) {
@ -1831,11 +1842,6 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
// and there is always one of those.
if (aChild && !isHiding) {
nsCOMPtr<nsPIAccessible> privateContainerAccessible =
do_QueryInterface(containerAccessible);
if (privateContainerAccessible) {
privateContainerAccessible->InvalidateChildren();
}
// Fire EVENT_SHOW, EVENT_MENUPOPUP_START for newly visible content.
// Fire after a short timer, because we want to make sure the view has been
// updated to make this accessible content visible. If we don't wait,