diff --git a/accessible/base/DocManager.cpp b/accessible/base/DocManager.cpp index 9011f20dad70..0c3fa5d3ba87 100644 --- a/accessible/base/DocManager.cpp +++ b/accessible/base/DocManager.cpp @@ -91,20 +91,22 @@ Accessible* DocManager::FindAccessibleInCache(nsINode* aNode) const { return nullptr; } -void DocManager::RemoveFromXPCDocumentCache(DocAccessible* aDocument) { +void DocManager::RemoveFromXPCDocumentCache(DocAccessible* aDocument, + bool aAllowServiceShutdown) { xpcAccessibleDocument* xpcDoc = mXPCDocumentCache.GetWeak(aDocument); if (xpcDoc) { xpcDoc->Shutdown(); mXPCDocumentCache.Remove(aDocument); - if (!HasXPCDocuments()) { + if (aAllowServiceShutdown && !HasXPCDocuments()) { MaybeShutdownAccService(nsAccessibilityService::eXPCOM); } } } void DocManager::NotifyOfDocumentShutdown(DocAccessible* aDocument, - Document* aDOMDocument) { + Document* aDOMDocument, + bool aAllowServiceShutdown) { // We need to remove listeners in both cases, when document is being shutdown // or when accessibility service is being shut down as well. RemoveListeners(aDOMDocument); @@ -115,7 +117,7 @@ void DocManager::NotifyOfDocumentShutdown(DocAccessible* aDocument, return; } - RemoveFromXPCDocumentCache(aDocument); + RemoveFromXPCDocumentCache(aDocument, aAllowServiceShutdown); mDocAccessibleCache.Remove(aDOMDocument); } diff --git a/accessible/base/DocManager.h b/accessible/base/DocManager.h index 5fd820ff46a8..81ff4e72b1ce 100644 --- a/accessible/base/DocManager.h +++ b/accessible/base/DocManager.h @@ -56,11 +56,15 @@ class DocManager : public nsIWebProgressListener, /** * Called by document accessible when it gets shutdown. + * @param aAllowServiceShutdown true to shut down nsAccessibilityService + * if it is no longer required, false to prevent it. */ void NotifyOfDocumentShutdown(DocAccessible* aDocument, - dom::Document* aDOMDocument); + dom::Document* aDOMDocument, + bool aAllowServiceShutdown = true); - void RemoveFromXPCDocumentCache(DocAccessible* aDocument); + void RemoveFromXPCDocumentCache(DocAccessible* aDocument, + bool aAllowServiceShutdown = true); /** * Return XPCOM accessible document. diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index 42357d02cd87..43cab7396dc9 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -396,6 +396,9 @@ void DocAccessible::Shutdown() { RemoveEventListeners(); + // mParent->RemoveChild clears mParent, but we need to know whether we were a + // child later, so use a flag. + const bool isChild = !!mParent; if (mParent) { DocAccessible* parentDocument = mParent->Document(); if (parentDocument) parentDocument->RemoveChildDocument(this); @@ -404,6 +407,9 @@ void DocAccessible::Shutdown() { MOZ_ASSERT(!mParent, "Parent has to be null!"); } + mPresShell->SetDocAccessible(nullptr); + mPresShell = nullptr; // Avoid reentrancy + // Walk the array backwards because child documents remove themselves from the // array as they are shutdown. int32_t childDocCount = mChildDocuments.Length(); @@ -424,9 +430,6 @@ void DocAccessible::Shutdown() { mVirtualCursor = nullptr; } - mPresShell->SetDocAccessible(nullptr); - mPresShell = nullptr; // Avoid reentrancy - mDependentIDsHashes.Clear(); mNodeToAccessibleMap.Clear(); @@ -446,7 +449,13 @@ void DocAccessible::Shutdown() { HyperTextAccessibleWrap::Shutdown(); - GetAccService()->NotifyOfDocumentShutdown(this, mDocumentNode); + MOZ_ASSERT(GetAccService()); + GetAccService()->NotifyOfDocumentShutdown( + this, mDocumentNode, + // Make sure we don't shut down AccService while a parent document is + // still shutting down. The parent will allow service shutdown when it + // reaches this point. + /* aAllowServiceShutdown */ !isChild); mDocumentNode = nullptr; }