From b81a48a4a5238b2d7a87d45048b92c77da1b75aa Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 14 Jun 2010 16:06:48 -0400 Subject: [PATCH] Bug 571459. Shutdown the doc accessible if its presshell dies. r=surkov,roc --- accessible/public/nsIAccessibilityService.h | 12 +++++++--- accessible/src/base/nsAccDocManager.h | 24 +++++++++---------- .../src/base/nsAccessibilityService.cpp | 12 ++++++++++ accessible/src/base/nsAccessibilityService.h | 2 ++ accessible/src/base/nsOuterDocAccessible.cpp | 20 +++------------- layout/base/nsPresShell.cpp | 10 ++++++++ 6 files changed, 48 insertions(+), 32 deletions(-) diff --git a/accessible/public/nsIAccessibilityService.h b/accessible/public/nsIAccessibilityService.h index ef3f34c5ed02..4f550248fde6 100644 --- a/accessible/public/nsIAccessibilityService.h +++ b/accessible/public/nsIAccessibilityService.h @@ -51,10 +51,10 @@ class nsIFrame; class nsIPresShell; class nsObjectFrame; -// 9f43b315-53c6-4d46-9818-9c8593e91984 +// 10ff6dca-b219-4b64-9a4c-67a62b86edce #define NS_IACCESSIBILITYSERVICE_IID \ -{0x9f43b315, 0x53c6, 0x4d46, \ - {0x98, 0x18, 0x9c, 0x85, 0x93, 0xe9, 0x19, 0x84} } +{ 0x10ff6dca, 0xb219, 0x4b64, \ + { 0x9a, 0x4c, 0x67, 0xa6, 0x2b, 0x86, 0xed, 0xce } } class nsIAccessibilityService : public nsIAccessibleRetrieval { @@ -174,6 +174,12 @@ public: */ virtual nsresult FireAccessibleEvent(PRUint32 aEvent, nsIAccessible *aTarget) = 0; + + /** + * Notify the accessibility service that the given presshell is + * being destroyed. + */ + virtual void PresShellDestroyed(nsIPresShell* aPresShell) = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIAccessibilityService, diff --git a/accessible/src/base/nsAccDocManager.h b/accessible/src/base/nsAccDocManager.h index 07b86ac3f75a..0d2084d88bf6 100644 --- a/accessible/src/base/nsAccDocManager.h +++ b/accessible/src/base/nsAccDocManager.h @@ -73,13 +73,6 @@ public: */ nsAccessible *FindAccessibleInCache(void *aUniqueID) const; - /** - * Shutdown document accessibles in the tree starting from the given one. - * - * @param aDocument [in] the DOM document of start document accessible - */ - void ShutdownDocAccessiblesInTree(nsIDocument *aDocument); - protected: nsAccDocManager() { }; @@ -93,6 +86,18 @@ protected: */ void Shutdown(); + /** + * Shutdown the document accessible. + */ + void ShutdownDocAccessible(nsIDocument *aDocument); + + /** + * Shutdown document accessibles in the tree starting from the given one. + * + * @param aDocument [in] the DOM document of start document accessible + */ + void ShutdownDocAccessiblesInTree(nsIDocument *aDocument); + private: nsAccDocManager(const nsAccDocManager&); nsAccDocManager& operator =(const nsAccDocManager&); @@ -148,11 +153,6 @@ private: void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem, nsIDocument *aDocument); - /** - * Shutdown the document accessible. - */ - void ShutdownDocAccessible(nsIDocument *aDocument); - typedef nsRefPtrHashtable nsDocAccessibleHashtable; diff --git a/accessible/src/base/nsAccessibilityService.cpp b/accessible/src/base/nsAccessibilityService.cpp index bd1335bf3c24..ff18ec20eaa9 100644 --- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -186,6 +186,18 @@ nsAccessibilityService::FireAccessibleEvent(PRUint32 aEvent, return NS_OK; } +void +nsAccessibilityService::PresShellDestroyed(nsIPresShell* aPresShell) +{ + // Presshell destruction will automatically destroy shells for + // descendant documents, so no need to worry about those. Just + // shut down the accessible for this one document. That keeps us + // from having bad behavior in case of deep bushy subtrees. + nsIDocument* doc = aPresShell->GetDocument(); + if (doc) + ShutdownDocAccessible(doc); +} + // nsAccessibilityService private nsresult nsAccessibilityService::GetInfo(nsIFrame *aFrame, nsIWeakReference **aShell, diff --git a/accessible/src/base/nsAccessibilityService.h b/accessible/src/base/nsAccessibilityService.h index 8d7bc638e3d2..97c5d1275cab 100644 --- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -126,6 +126,8 @@ public: virtual nsresult FireAccessibleEvent(PRUint32 aEvent, nsIAccessible *aTarget); + virtual void PresShellDestroyed(nsIPresShell* aPresShell); + // nsAccessibiltiyService /** diff --git a/accessible/src/base/nsOuterDocAccessible.cpp b/accessible/src/base/nsOuterDocAccessible.cpp index 96158df2903f..bc4e8b6747da 100644 --- a/accessible/src/base/nsOuterDocAccessible.cpp +++ b/accessible/src/base/nsOuterDocAccessible.cpp @@ -159,15 +159,6 @@ nsOuterDocAccessible::DoAction(PRUint8 aIndex) void nsOuterDocAccessible::Shutdown() { - // Shutdown child document if any. - nsAccessible *childAcc = mChildren.SafeElementAt(0, nsnull); - if (childAcc) { - nsRefPtr docAcc(do_QueryObject(childAcc)); - NS_LOG_ACCDOCDESTROY_FOR("outerdoc document shutdown", - docAcc->GetDOMDocument(), docAcc.get()) - GetAccService()->ShutdownDocAccessiblesInTree(docAcc->GetDOMDocument()); - } - nsAccessible::InvalidateChildren(); nsAccessibleWrap::Shutdown(); @@ -179,14 +170,9 @@ nsOuterDocAccessible::Shutdown() void nsOuterDocAccessible::InvalidateChildren() { - // Do not invalidate children because nsAccDocManager is responsible for - // document accessible lifetime when DOM document is created or destroyed. If - // DOM document isn't destroyed but its presshell is destroyed (for example, - // when DOM node of outerdoc accessible is hidden), then outerdoc accessible - // notifies nsAccDocManager about this. If presshell is created for existing - // DOM document (for example when DOM node of outerdoc accessible is shown) - // then allow nsAccDocManager to handle this case since the document - // accessible is created and appended as a child when it's requested. + // Do not invalidate children because nsAccDocManager is responsible + // for document accessible lifetime when DOM document or its + // presshell is created or destroyed. mAreChildrenInitialized = PR_FALSE; } diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 7b9e87f771eb..dc18e5f5ac1e 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1816,6 +1816,16 @@ PresShell::Destroy() if (mHaveShutDown) return; +#ifdef ACCESSIBILITY + if (gIsAccessibilityActive) { + nsCOMPtr accService = + do_GetService("@mozilla.org/accessibilityService;1"); + if (accService) { + accService->PresShellDestroyed(this); + } + } +#endif // ACCESSIBILITY + MaybeReleaseCapturingContent(); mContentToScrollTo = nsnull;