From b9b500e77b62da6a0d19f63327a3f649f40817b5 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Fri, 18 Jun 2010 11:44:09 +0900 Subject: [PATCH] Bug 571459 - shutdown document accessible when presshell goes away, patch=bz, surkov, r=surkov, davidb, sr=roc, bz, f=marcoz --- accessible/public/nsIAccessibilityService.h | 12 ++- accessible/src/base/nsAccDocManager.cpp | 65 ++++--------- accessible/src/base/nsAccDocManager.h | 94 ++++++++++++------- accessible/src/base/nsAccessNode.h | 2 + .../src/base/nsAccessibilityService.cpp | 19 ++++ accessible/src/base/nsAccessibilityService.h | 2 + accessible/src/base/nsDocAccessible.cpp | 4 +- accessible/src/base/nsDocAccessible.h | 2 - accessible/src/base/nsOuterDocAccessible.cpp | 28 ++++-- accessible/tests/mochitest/events.js | 8 ++ layout/base/nsPresShell.cpp | 10 ++ 11 files changed, 154 insertions(+), 92 deletions(-) diff --git a/accessible/public/nsIAccessibilityService.h b/accessible/public/nsIAccessibilityService.h index ef3f34c5ed0..f8ab5e11a69 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 { @@ -166,6 +166,12 @@ public: */ virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget) = 0; + /** + * Notify the accessibility service that the given presshell is + * being destroyed. + */ + virtual void PresShellDestroyed(nsIPresShell *aPresShell) = 0; + /** * Fire accessible event of the given type for the given target. * diff --git a/accessible/src/base/nsAccDocManager.cpp b/accessible/src/base/nsAccDocManager.cpp index c5dda6287a0..cce78621e22 100644 --- a/accessible/src/base/nsAccDocManager.cpp +++ b/accessible/src/base/nsAccDocManager.cpp @@ -96,6 +96,7 @@ nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocument *aDocument) ShutdownDocAccessiblesInTree(treeItem, aDocument); } + //////////////////////////////////////////////////////////////////////////////// // nsAccDocManager protected @@ -128,6 +129,22 @@ nsAccDocManager::Shutdown() ClearDocCache(); } +void +nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument) +{ + nsDocAccessible* docAccessible = + mDocAccessibleCache.GetWeak(static_cast(aDocument)); + if (!docAccessible) + return; + + // We're allowed to not remove listeners when accessible document is shutdown + // since we don't keep strong reference on chrome event target and listeners + // are removed automatically when chrome event target goes away. + + docAccessible->Shutdown(); + mDocAccessibleCache.Remove(static_cast(aDocument)); +} + //////////////////////////////////////////////////////////////////////////////// // nsISupports @@ -413,30 +430,6 @@ nsAccDocManager::AddListeners(nsIDocument *aDocument, } } -void -nsAccDocManager::RemoveListeners(nsIDocument *aDocument) -{ - // Document has no window when application shuts down. The document can still - // exist because we didn't receive a "pagehide" event. - nsPIDOMWindow *window = aDocument->GetWindow(); - if (!window) - return; - - nsPIDOMEventTarget *target = window->GetChromeEventHandler(); - nsIEventListenerManager* elm = target->GetListenerManager(PR_TRUE); - elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"), - NS_EVENT_FLAG_CAPTURE, nsnull); - - NS_LOG_ACCDOCDESTROY("removed 'pagehide' listener", aDocument) - - if (nsCoreUtils::IsRootDocument(aDocument)) { - elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"), - NS_EVENT_FLAG_CAPTURE, nsnull); - - NS_LOG_ACCDOCDESTROY("removed 'DOMContentLoaded' listener", aDocument) - } -} - nsDocAccessible* nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument) { @@ -502,7 +495,6 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument) if (outerDocAcc) { // Root document accessible doesn't have associated outerdoc accessible, it // adds itself to application accessible instead. - NS_LOG_ACCDOCCREATE("append document to outerdoc", aDocument) outerDocAcc->AppendChild(docAcc); } @@ -512,7 +504,7 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument) return nsnull; } - NS_LOG_ACCDOCCREATE("document created", aDocument) + NS_LOG_ACCDOCCREATE("document creation finished", aDocument) AddListeners(aDocument, isRootDoc); return docAcc; @@ -547,19 +539,6 @@ nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem, ShutdownDocAccessible(aDocument); } -void -nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument) -{ - RemoveListeners(aDocument); - - nsDocAccessible *docAccessible = - mDocAccessibleCache.GetWeak(static_cast(aDocument)); - if (docAccessible) - docAccessible->Shutdown(); - - mDocAccessibleCache.Remove(static_cast(aDocument)); -} - //////////////////////////////////////////////////////////////////////////////// // nsAccDocManager static @@ -573,14 +552,8 @@ nsAccDocManager::ClearDocCacheEntry(const void* aKey, NS_ASSERTION(aDocAccessible, "Calling ClearDocCacheEntry with a NULL pointer!"); - if (aDocAccessible) { - nsCOMPtr document = aDocAccessible->GetDOMDocument(); - NS_ASSERTION(document, "Document accessible was shutdown already!"); - if (document) - accDocMgr->RemoveListeners(document); - + if (aDocAccessible) aDocAccessible->Shutdown(); - } return PL_DHASH_REMOVE; } diff --git a/accessible/src/base/nsAccDocManager.h b/accessible/src/base/nsAccDocManager.h index 2052660e0c6..a0d060ad251 100644 --- a/accessible/src/base/nsAccDocManager.h +++ b/accessible/src/base/nsAccDocManager.h @@ -48,6 +48,8 @@ class nsDocAccessible; +//#define DEBUG_ACCDOCMGR + /** * Manage the document accessible life cycle. */ @@ -80,6 +82,14 @@ public: */ void ShutdownDocAccessiblesInTree(nsIDocument *aDocument); + /** + * Return document accessible from the cache. Convenient method for testing. + */ + inline nsDocAccessible* GetDocAccessibleFromCache(nsIDocument* aDocument) const + { + return mDocAccessibleCache.GetWeak(static_cast(aDocument)); + } + protected: nsAccDocManager() { }; @@ -93,10 +103,10 @@ protected: */ void Shutdown(); - inline nsDocAccessible* GetDocAccessibleFromCache(nsIDocument* aDocument) const - { - return mDocAccessibleCache.GetWeak(static_cast(aDocument)); - } + /** + * Shutdown the document accessible. + */ + void ShutdownDocAccessible(nsIDocument* aDocument); private: nsAccDocManager(const nsAccDocManager&); @@ -137,10 +147,9 @@ private: PRBool IsEventTargetDocument(nsIDocument *aDocument) const; /** - * Add/remove 'pagehide' and 'DOMContentLoaded' event listeners. + * Add 'pagehide' and 'DOMContentLoaded' event listeners. */ void AddListeners(nsIDocument *aDocument, PRBool aAddPageShowListener); - void RemoveListeners(nsIDocument *aDocument); /** * Create document or root accessible. @@ -153,11 +162,6 @@ private: void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem, nsIDocument *aDocument); - /** - * Shutdown the document accessible. - */ - void ShutdownDocAccessible(nsIDocument *aDocument); - typedef nsRefPtrHashtable nsDocAccessibleHashtable; @@ -194,8 +198,6 @@ private: /** * nsAccDocManager debugging macros. */ -//#define DEBUG_ACCDOCMGR - #ifdef DEBUG_ACCDOCMGR // Enable these to log accessible document loading, creation or destruction. @@ -205,9 +207,7 @@ private: // Common macros, do not use directly. #define NS_LOG_ACCDOC_ADDRESS(aDocument, aDocAcc) \ - printf("DOM id: 0x%x, acc id: 0x%x", \ - reinterpret_cast(static_cast(aDocument)), \ - reinterpret_cast(aDocAcc)); + printf("DOM id: %p, acc id: %p", aDocument, aDocAcc); #define NS_LOG_ACCDOC_URI(aDocument) \ nsIURI *uri = aDocument->GetDocumentURI(); \ @@ -260,19 +260,18 @@ private: #define NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \ nsIPresShell *ps = aDocument->GetPrimaryShell(); \ - printf("presshell: 0x%x", reinterpret_cast(ps)); \ + printf("presshell: %p", ps); \ nsIScrollableFrame *sf = ps ? \ ps->GetRootScrollFrameAsScrollableExternal() : nsnull; \ - printf(", root scroll frame: 0x%x", reinterpret_cast(sf)); + printf(", root scroll frame: %p", sf); #define NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \ nsCOMPtr loadGroup = aDocument->GetDocumentLoadGroup(); \ - printf("load group: 0x%x", reinterpret_cast(loadGroup.get())); + printf("load group: %p", loadGroup); #define NS_LOG_ACCDOC_DOCPARENT(aDocument) \ nsIDocument *parentDoc = aDocument->GetParentDocument(); \ - printf("parent id: 0x%x", \ - reinterpret_cast(parentDoc)); \ + printf("parent id: %p", parentDoc); \ if (parentDoc) { \ printf("\n parent "); \ NS_LOG_ACCDOC_URI(parentDoc) \ @@ -397,6 +396,21 @@ private: } \ } +#define NS_LOG_ACCDOC_ACCADDRESS(aName, aAcc) \ + { \ + nsINode* node = aAcc->GetNode(); \ + nsIDocument* doc = aAcc->GetDocumentNode(); \ + nsDocAccessible *docacc = GetAccService()->GetDocAccessibleFromCache(doc); \ + printf(" " aName " accessible: %p, node: %p\n", aAcc, node); \ + printf(" docacc for " aName " accessible: %p, node: %p\n", docacc, doc); \ + printf(" "); \ + NS_LOG_ACCDOC_URI(doc) \ + printf("\n"); \ + } + +#define NS_LOG_ACCDOC_MSG(aMsg) \ + printf("\n" aMsg "\n"); \ + #define NS_LOG_ACCDOC_TEXT(aMsg) \ printf(" " aMsg "\n"); @@ -431,7 +445,7 @@ private: #define NS_LOG_ACCDOCLOAD(aMsg, aWebProgress, aRequest, aStateFlags) \ { \ - printf("\nA11Y DOCLOAD: " aMsg "\n"); \ + NS_LOG_ACCDOC_MSG("A11Y DOCLOAD: " aMsg); \ \ nsCOMPtr DOMWindow; \ aWebProgress->GetDOMWindow(getter_AddRefs(DOMWindow)); \ @@ -441,7 +455,7 @@ private: if (DOMDocument) { \ nsCOMPtr document(do_QueryInterface(DOMDocument)); \ nsDocAccessible *docAcc = \ - mDocAccessibleCache.GetWeak(static_cast(document)); \ + GetAccService()->GetDocAccessibleFromCache(document); \ NS_LOG_ACCDOC_DOCINFO(document, docAcc) \ \ printf(" {\n"); \ @@ -463,9 +477,9 @@ private: #define NS_LOG_ACCDOCLOAD2(aMsg, aDocument) \ { \ - printf("\nA11Y DOCLOAD: " aMsg "\n"); \ + NS_LOG_ACCDOC_MSG("A11Y DOCLOAD: " aMsg); \ nsDocAccessible *docAcc = \ - mDocAccessibleCache.GetWeak(static_cast(aDocument)); \ + GetAccService()->GetDocAccessibleFromCache(aDocument); \ NS_LOG_ACCDOC_DOCINFO(aDocument, docAcc) \ } @@ -496,16 +510,19 @@ private: // Accessible document creation macros. #ifdef DEBUG_ACCDOCMGR_DOCCREATE #define NS_LOG_ACCDOCCREATE_FOR(aMsg, aDocument, aDocAcc) \ - printf("\nA11Y DOCCREATE: " aMsg "\n"); \ + NS_LOG_ACCDOC_MSG("A11Y DOCCREATE: " aMsg); \ NS_LOG_ACCDOC_DOCINFO(aDocument, aDocAcc) #define NS_LOG_ACCDOCCREATE(aMsg, aDocument) \ { \ nsDocAccessible *docAcc = \ - mDocAccessibleCache.GetWeak(static_cast(aDocument)); \ + GetAccService()->GetDocAccessibleFromCache(aDocument); \ NS_LOG_ACCDOCCREATE_FOR(aMsg, aDocument, docAcc) \ } +#define NS_LOG_ACCDOCCREATE_ACCADDRESS(aName, aAcc) \ + NS_LOG_ACCDOC_ACCADDRESS(aName, aAcc) + #define NS_LOG_ACCDOCCREATE_TEXT(aMsg) \ NS_LOG_ACCDOC_TEXT(aMsg) @@ -514,16 +531,24 @@ private: // Accessible document destruction macros. #ifdef DEBUG_ACCDOCMGR_DOCDESTROY #define NS_LOG_ACCDOCDESTROY_FOR(aMsg, aDocument, aDocAcc) \ - printf("\nA11Y DOCDESTROY: " aMsg "\n"); \ + NS_LOG_ACCDOC_MSG("A11Y DOCDESTROY: " aMsg); \ NS_LOG_ACCDOC_DOCINFO(aDocument, aDocAcc) #define NS_LOG_ACCDOCDESTROY(aMsg, aDocument) \ - nsDocAccessible *docAcc = \ - mDocAccessibleCache.GetWeak(static_cast(aDocument)); \ - NS_LOG_ACCDOCDESTROY_FOR(aMsg, aDocument, docAcc) + { \ + nsDocAccessible* docAcc = \ + GetAccService()->GetDocAccessibleFromCache(aDocument); \ + NS_LOG_ACCDOCDESTROY_FOR(aMsg, aDocument, docAcc) \ + } -#define NS_LOG_ACCDOCDESTROY_TEXT(aMsg) \ - NS_LOG_ACCDOC_TEXT(aMsg) +#define NS_LOG_ACCDOCDESTROY_ACCADDRESS(aName, aAcc) \ + NS_LOG_ACCDOC_ACCADDRESS(aName, aAcc) + +#define NS_LOG_ACCDOCDESTROY_MSG(aMsg) \ + NS_LOG_ACCDOC_MSG(aMsg) + +#define NS_LOG_ACCDOCDESTROY_TEXT(aMsg) \ + NS_LOG_ACCDOC_TEXT(aMsg) #endif // DEBUG_ACCDOCMGR_DOCDESTROY @@ -541,12 +566,15 @@ private: #ifndef DEBUG_ACCDOCMGR_DOCCREATE #define NS_LOG_ACCDOCCREATE_FOR(aMsg, aDocument, aDocAcc) #define NS_LOG_ACCDOCCREATE(aMsg, aDocument) +#define NS_LOG_ACCDOCCREATE_ACCADDRESS(aName, aAcc) #define NS_LOG_ACCDOCCREATE_TEXT(aMsg) #endif #ifndef DEBUG_ACCDOCMGR_DOCDESTROY #define NS_LOG_ACCDOCDESTROY_FOR(aMsg, aDocument, aDocAcc) #define NS_LOG_ACCDOCDESTROY(aMsg, aDocument) +#define NS_LOG_ACCDOCDESTROY_MSG(aMsg) +#define NS_LOG_ACCDOCDESTROY_ACCADDRESS(aName, aAcc) #define NS_LOG_ACCDOCDESTROY_TEXT(aMsg) #endif diff --git a/accessible/src/base/nsAccessNode.h b/accessible/src/base/nsAccessNode.h index 18b4b63bfcb..4c81b6a3ac8 100644 --- a/accessible/src/base/nsAccessNode.h +++ b/accessible/src/base/nsAccessNode.h @@ -157,6 +157,8 @@ public: */ virtual nsINode* GetNode() const { return mContent; } nsIContent* GetContent() const { return mContent; } + nsIDocument* GetDocumentNode() const + { return mContent ? mContent->GetOwnerDoc() : nsnull; } /** * Return node type information of DOM node associated with the accessible. diff --git a/accessible/src/base/nsAccessibilityService.cpp b/accessible/src/base/nsAccessibilityService.cpp index a7ecb24b450..668be79428f 100644 --- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -780,6 +780,25 @@ nsAccessibilityService::CreateHTMLCaptionAccessible(nsIFrame *aFrame, 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. + // When document subtree containing iframe is hidden then we don't get + // pagehide event for the iframe's underlying document and its presshell is + // destroyed before we're notified styles were changed. Shutdown the document + // accessible early. + nsIDocument* doc = aPresShell->GetDocument(); + if (!doc) + return; + + NS_LOG_ACCDOCDESTROY("presshell destroyed", doc) + ShutdownDocAccessible(doc); +} + // nsAccessibilityService protected nsAccessible * nsAccessibilityService::GetCachedAccessible(nsINode *aNode, diff --git a/accessible/src/base/nsAccessibilityService.h b/accessible/src/base/nsAccessibilityService.h index 8d7bc638e3d..15d551b9ae2 100644 --- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -124,6 +124,8 @@ public: virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget); + virtual void PresShellDestroyed(nsIPresShell* aPresShell); + virtual nsresult FireAccessibleEvent(PRUint32 aEvent, nsIAccessible *aTarget); // nsAccessibiltiyService diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index 0e15319fe7f..94282e6e30a 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -596,6 +596,8 @@ nsDocAccessible::RemoveAccessNodeFromCache(nsAccessible *aAccessible) PRBool nsDocAccessible::Init() { + NS_LOG_ACCDOCCREATE_FOR("document initialize", mDocument, this) + // Initialize event queue. mEventQueue = new nsAccEventQueue(this); if (!mEventQueue) @@ -630,8 +632,8 @@ nsDocAccessible::Shutdown() RemoveEventListeners(); if (mParent) { - NS_LOG_ACCDOCDESTROY_FOR("remove document from outer doc", mDocument, this); mParent->RemoveChild(this); + mParent = nsnull; } mWeakShell = nsnull; // Avoid reentrancy diff --git a/accessible/src/base/nsDocAccessible.h b/accessible/src/base/nsDocAccessible.h index 504be57d575..ea7cf36d8cb 100644 --- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -124,8 +124,6 @@ public: // nsDocAccessible - nsIDocument *GetDOMDocument() const { return mDocument; } - /** * Return true if associated DOM document was loaded and isn't unloading. */ diff --git a/accessible/src/base/nsOuterDocAccessible.cpp b/accessible/src/base/nsOuterDocAccessible.cpp index 96158df2903..ce587dc5ea1 100644 --- a/accessible/src/base/nsOuterDocAccessible.cpp +++ b/accessible/src/base/nsOuterDocAccessible.cpp @@ -159,17 +159,20 @@ nsOuterDocAccessible::DoAction(PRUint8 aIndex) void nsOuterDocAccessible::Shutdown() { - // Shutdown child document if any. + // XXX: sometimes outerdoc accessible is shutdown because of layout style + // change however the presshell of underlying document isn't destroyed and + // the document doesn't get pagehide events. Shutdown underlying document if + // any to avoid hanging document accessible. + NS_LOG_ACCDOCDESTROY_MSG("A11y outerdoc shutdown") + NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this) + 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()); + NS_LOG_ACCDOCDESTROY("outerdoc's child document shutdown", + childAcc->GetDocumentNode()) + GetAccService()->ShutdownDocAccessiblesInTree(childAcc->GetDocumentNode()); } - nsAccessible::InvalidateChildren(); - nsAccessibleWrap::Shutdown(); } @@ -201,6 +204,11 @@ nsOuterDocAccessible::AppendChild(nsAccessible *aAccessible) return PR_FALSE; aAccessible->SetParent(this); + + NS_LOG_ACCDOCCREATE("append document to outerdoc", + aAccessible->GetDocumentNode()) + NS_LOG_ACCDOCCREATE_ACCADDRESS("outerdoc", this) + return PR_TRUE; } @@ -213,13 +221,19 @@ nsOuterDocAccessible::RemoveChild(nsAccessible *aAccessible) return PR_FALSE; } + NS_LOG_ACCDOCDESTROY("remove document from outerdoc", + child->GetDocumentNode()) + NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this) + mChildren.RemoveElement(child); + NS_ASSERTION(!mChildren.Length(), "This child document of outerdoc accessible wasn't removed!"); return PR_TRUE; } + //////////////////////////////////////////////////////////////////////////////// // nsAccessible protected diff --git a/accessible/tests/mochitest/events.js b/accessible/tests/mochitest/events.js index d6bd3c0f276..cc8db11a570 100644 --- a/accessible/tests/mochitest/events.js +++ b/accessible/tests/mochitest/events.js @@ -25,6 +25,11 @@ const EVENT_VALUE_CHANGE = nsIAccessibleEvent.EVENT_VALUE_CHANGE; */ var gA11yEventDumpID = ""; +/** + * Set up this variable to dump event processing into console. + */ +var gA11yEventDumpToConsole = false; + /** * Executes the function when requested event is handled. * @@ -262,6 +267,9 @@ function eventQueue(aEventType) this.setEventHandler(invoker); + if (gA11yEventDumpToConsole) + dump("\nEvent queue: \n invoke: " + invoker.getID() + "\n"); + if (invoker.invoke() == INVOKER_ACTION_FAILED) { // Invoker failed to prepare action, fail and finish tests. this.processNextInvoker(); diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index fb41c56f73b..3a35d9af9fc 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;