From 082408ed24f2b6656d5f48386f5586855f50fb26 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Fri, 12 Nov 2010 14:00:55 -0500 Subject: [PATCH] Bug 545465 - don't keep rejected accessible in the cache, r=ginn.chen, davidb, a=blockingBetaN --- accessible/src/base/nsAccDocManager.cpp | 27 ++++--- .../src/base/nsAccessibilityService.cpp | 60 ++++++-------- accessible/src/base/nsAccessibilityService.h | 13 --- accessible/src/base/nsAccessible.cpp | 27 ------- accessible/src/base/nsAccessible.h | 8 -- accessible/src/base/nsDocAccessible.cpp | 80 ++++++++++++------- accessible/src/base/nsDocAccessible.h | 14 ++-- .../src/html/nsHTMLImageMapAccessible.cpp | 17 ++-- .../src/html/nsHTMLSelectAccessible.cpp | 16 ++-- accessible/src/html/nsHTMLTextAccessible.cpp | 3 +- .../src/xul/nsXULColorPickerAccessible.cpp | 4 + .../src/xul/nsXULFormControlAccessible.cpp | 5 ++ accessible/src/xul/nsXULTreeAccessible.cpp | 48 +++++------ .../src/xul/nsXULTreeGridAccessible.cpp | 27 +++---- 14 files changed, 153 insertions(+), 196 deletions(-) diff --git a/accessible/src/base/nsAccDocManager.cpp b/accessible/src/base/nsAccDocManager.cpp index f64fd16136b..f36473f10f7 100644 --- a/accessible/src/base/nsAccDocManager.cpp +++ b/accessible/src/base/nsAccDocManager.cpp @@ -456,28 +456,29 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument) // We only create root accessibles for the true root, otherwise create a // doc accessible. nsCOMPtr weakShell(do_GetWeakReference(presShell)); - nsDocAccessible *docAcc = isRootDoc ? + nsRefPtr docAcc = isRootDoc ? new nsRootAccessibleWrap(aDocument, rootElm, weakShell) : new nsDocAccessibleWrap(aDocument, rootElm, weakShell); - if (!docAcc) + // Cache the document accessible into document cache. + if (!docAcc || !mDocAccessibleCache.Put(aDocument, docAcc)) return nsnull; - // Cache and addref document accessible. - if (!mDocAccessibleCache.Put(aDocument, docAcc)) { - delete docAcc; - return nsnull; - } - - // XXX: ideally we should initialize an accessible and then put it into tree, - // we can't since document accessible fires reorder event on its container - // while initialized. - if (!outerDocAcc->AppendChild(docAcc) || - !GetAccService()->InitAccessible(docAcc, nsAccUtils::GetRoleMapEntry(aDocument))) { + // Bind the document accessible into tree. + if (!outerDocAcc->AppendChild(docAcc)) { mDocAccessibleCache.Remove(aDocument); return nsnull; } + // Initialize the document accessible. Note, Init() should be called after + // the document accessible is bound to the tree. + if (!docAcc->Init()) { + docAcc->Shutdown(); + mDocAccessibleCache.Remove(aDocument); + return nsnull; + } + docAcc->SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aDocument)); + NS_LOG_ACCDOCCREATE("document creation finished", aDocument) AddListeners(aDocument, isRootDoc); diff --git a/accessible/src/base/nsAccessibilityService.cpp b/accessible/src/base/nsAccessibilityService.cpp index 30c537e727a..e24c6f0c8d0 100644 --- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -837,28 +837,6 @@ nsAccessibilityService::GetCachedAccessibleOrContainer(nsINode* aNode) return accessible; } -PRBool -nsAccessibilityService::InitAccessible(nsAccessible *aAccessible, - nsRoleMapEntry *aRoleMapEntry) -{ - if (!aAccessible) - return PR_FALSE; - - // Add to cache an accessible, etc. - if (!aAccessible->Init()) { - NS_ERROR("Failed to initialize an accessible!"); - - aAccessible->Shutdown(); - return PR_FALSE; - } - - NS_ASSERTION(aAccessible->IsInCache(), - "Initialized accessible not in the cache!"); - - aAccessible->SetRoleMapEntry(aRoleMapEntry); - return PR_TRUE; -} - static PRBool HasRelatedContent(nsIContent *aContent) { nsAutoString id; @@ -958,6 +936,13 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode, return areaAcc; } + nsDocAccessible* docAcc = + GetAccService()->GetDocAccessible(aNode->GetOwnerDoc()); + if (!docAcc) { + NS_NOTREACHED("No document for accessible being created!"); + return nsnull; + } + // Attempt to create an accessible based on what we know. nsRefPtr newAcc; if (content->IsNodeOfType(nsINode::eTEXT)) { @@ -976,7 +961,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode, } if (weakFrame.IsAlive()) { newAcc = weakFrame.GetFrame()->CreateAccessible(); - if (InitAccessible(newAcc, nsnull)) + if (docAcc->BindToDocument(newAcc, nsnull)) return newAcc.forget(); return nsnull; } @@ -1004,7 +989,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode, } newAcc = new nsHyperTextAccessibleWrap(content, aWeakShell); - if (InitAccessible(newAcc, nsAccUtils::GetRoleMapEntry(aNode))) + if (docAcc->BindToDocument(newAcc, nsAccUtils::GetRoleMapEntry(aNode))) return newAcc.forget(); return nsnull; } @@ -1191,7 +1176,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode, } } - if (InitAccessible(newAcc, roleMapEntry)) + if (docAcc->BindToDocument(newAcc, roleMapEntry)) return newAcc.forget(); return nsnull; } @@ -1348,22 +1333,29 @@ nsAccessibilityService::GetAreaAccessible(nsIFrame* aImageFrame, // Try to get image map accessible from the global cache or create it // if failed. - nsRefPtr imageAcc = - GetCachedAccessible(aImageFrame->GetContent(), aWeakShell); - if (!imageAcc) { - imageAcc = CreateHTMLImageAccessible(aImageFrame->GetContent(), - aImageFrame->PresContext()->PresShell()); + nsRefPtr image = GetCachedAccessible(aImageFrame->GetContent(), + aWeakShell); + if (!image) { + image = CreateHTMLImageAccessible(aImageFrame->GetContent(), + aImageFrame->PresContext()->PresShell()); - if (!InitAccessible(imageAcc, nsnull)) + nsDocAccessible* document = + GetAccService()->GetDocAccessible(aAreaNode->GetOwnerDoc()); + if (!document) { + NS_NOTREACHED("No document for accessible being created!"); + return nsnull; + } + + if (!document->BindToDocument(image, nsnull)) return nsnull; } if (aImageAccessible) - *aImageAccessible = imageAcc; + *aImageAccessible = image; // Make sure accessible children of the image map are cached so // that they should be available in global cache. - imageAcc->EnsureChildren(); + image->EnsureChildren(); return GetCachedAccessible(aAreaNode, aWeakShell); } @@ -1771,7 +1763,7 @@ nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible) if (!applicationAcc) return nsnull; - nsNativeRootAccessibleWrap* nativeRootAcc = + nsRefPtr nativeRootAcc = new nsNativeRootAccessibleWrap((AtkObject*)aAtkAccessible); if (!nativeRootAcc) return nsnull; diff --git a/accessible/src/base/nsAccessibilityService.h b/accessible/src/base/nsAccessibilityService.h index d8f5eadc5be..b1e48843906 100644 --- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -202,19 +202,6 @@ public: GetCachedAccessibleOrContainer(aNode->GetNodeParent()) : nsnull; } - /** - * Initialize an accessible and cache it. The method should be called for - * every created accessible. - * - * @param aAccessible [in] accessible to initialize. - * @param aRoleMapEntry [in] the role map entry role the ARIA role or nsnull - * if none - * - * @return true if the accessible was initialized, otherwise false - */ - PRBool InitAccessible(nsAccessible *aAccessible, - nsRoleMapEntry *aRoleMapEntry); - protected: /** * Return an accessible for the DOM node in the given presentation shell if diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index 8257b229906..e0e0753bdb2 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -2621,19 +2621,6 @@ nsAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLe //////////////////////////////////////////////////////////////////////////////// // nsAccessNode public methods -PRBool -nsAccessible::Init() -{ - if (!nsAccessNodeWrap::Init()) - return PR_FALSE; - - nsDocAccessible* document = - GetAccService()->GetDocAccessible(mContent->GetOwnerDoc()); - NS_ASSERTION(document, "Cannot cache new nsAccessible!"); - - return document ? document->CacheAccessible(this) : PR_FALSE; -} - void nsAccessible::Shutdown() { @@ -2912,20 +2899,6 @@ nsAccessible::GetIndexOfEmbeddedChild(nsAccessible* aChild) return GetIndexOf(aChild); } -#ifdef DEBUG -PRBool -nsAccessible::IsInCache() -{ - nsDocAccessible *docAccessible = - GetAccService()->GetDocAccessible(mContent->GetOwnerDoc()); - if (docAccessible) - return docAccessible->GetCachedAccessibleByUniqueID(UniqueID()) ? PR_TRUE : PR_FALSE; - - return PR_FALSE; -} -#endif - - //////////////////////////////////////////////////////////////////////////////// // HyperLinkAccessible methods diff --git a/accessible/src/base/nsAccessible.h b/accessible/src/base/nsAccessible.h index c6f5560fb5c..8c54989b328 100644 --- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -113,7 +113,6 @@ public: ////////////////////////////////////////////////////////////////////////////// // nsAccessNode - virtual PRBool Init(); virtual void Shutdown(); ////////////////////////////////////////////////////////////////////////////// @@ -298,13 +297,6 @@ public: PRBool AreChildrenCached() const { return mChildrenFlags != eChildrenUninitialized; } bool IsBoundToParent() const { return mParent; } -#ifdef DEBUG - /** - * Return true if the access node is cached. - */ - PRBool IsInCache(); -#endif - ////////////////////////////////////////////////////////////////////////////// // Miscellaneous methods diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index e4ec97bb199..502f37fa7ec 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -599,31 +599,6 @@ nsDocAccessible::GetCachedAccessible(nsINode *aNode) return accessible; } -// nsDocAccessible public method -PRBool -nsDocAccessible::CacheAccessible(nsAccessible* aAccessible) -{ - if (aAccessible->IsPrimaryForNode() && - !mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible)) - return PR_FALSE; - - return mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible); -} - -// nsDocAccessible public method -void -nsDocAccessible::ShutdownAccessible(nsAccessible *aAccessible) -{ - // Remove an accessible from node to accessible map if it is presented there. - if (aAccessible->IsPrimaryForNode() && - mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible) - mNodeToAccessibleMap.Remove(aAccessible->GetNode()); - - void* uniqueID = aAccessible->UniqueID(); - aAccessible->Shutdown(); - mAccessibleCache.Remove(uniqueID); -} - //////////////////////////////////////////////////////////////////////////////// // nsAccessNode @@ -1345,6 +1320,55 @@ nsDocAccessible::GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID) return nsnull; } +bool +nsDocAccessible::BindToDocument(nsAccessible* aAccessible, + nsRoleMapEntry* aRoleMapEntry) +{ + if (!aAccessible) + return false; + + // Put into DOM node cache. + if (aAccessible->IsPrimaryForNode() && + !mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible)) + return false; + + // Put into unique ID cache. + if (!mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible)) { + if (aAccessible->IsPrimaryForNode()) + mNodeToAccessibleMap.Remove(aAccessible->GetNode()); + return false; + } + + // Initialize the accessible. + if (!aAccessible->Init()) { + NS_ERROR("Failed to initialize an accessible!"); + + UnbindFromDocument(aAccessible); + return false; + } + + aAccessible->SetRoleMapEntry(aRoleMapEntry); + return true; +} + +void +nsDocAccessible::UnbindFromDocument(nsAccessible* aAccessible) +{ + // Remove an accessible from node to accessible map if it is presented there. + if (aAccessible->IsPrimaryForNode() && + mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible) + mNodeToAccessibleMap.Remove(aAccessible->GetNode()); + +#ifdef DEBUG + NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()), + "Illegitimate illegitimated accessible!"); +#endif + + void* uniqueID = aAccessible->UniqueID(); + aAccessible->Shutdown(); + mAccessibleCache.Remove(uniqueID); +} + void nsDocAccessible::UpdateTree(nsIContent* aContainerNode, nsIContent* aStartNode, @@ -1761,10 +1785,6 @@ nsDocAccessible::UncacheChildrenInSubtree(nsAccessible* aRoot) void nsDocAccessible::ShutdownChildrenInSubtree(nsAccessible* aAccessible) { -#ifdef DEBUG - nsAccessible* incache = mAccessibleCache.GetWeak(aAccessible->UniqueID()); -#endif - // Traverse through children and shutdown them before this accessible. When // child gets shutdown then it removes itself from children array of its //parent. Use jdx index to process the cases if child is not attached to the @@ -1780,6 +1800,6 @@ nsDocAccessible::ShutdownChildrenInSubtree(nsAccessible* aAccessible) ShutdownChildrenInSubtree(child); } - ShutdownAccessible(aAccessible); + UnbindFromDocument(aAccessible); } diff --git a/accessible/src/base/nsDocAccessible.h b/accessible/src/base/nsDocAccessible.h index 5c678974764..e56d53a727f 100644 --- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -211,18 +211,18 @@ public: nsAccessible* GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID); /** - * Cache the accessible. + * Initialize the newly created accessible and put it into document caches. * - * @param aAccessible [in] accessible to cache - * - * @return true if accessible being cached, otherwise false + * @param aAccessible [in] created accessible + * @param aRoleMapEntry [in] the role map entry role the ARIA role or nsnull + * if none */ - PRBool CacheAccessible(nsAccessible *aAccessible); + bool BindToDocument(nsAccessible* aAccessible, nsRoleMapEntry* aRoleMapEntry); /** - * Shutdown the accessible and remove it from document cache. + * Remove the existing accessible from document caches and shutdown it. */ - void ShutdownAccessible(nsAccessible *aAccessible); + void UnbindFromDocument(nsAccessible* aAccessible); /** * Process the event when the queue of pending events is untwisted. Fire diff --git a/accessible/src/html/nsHTMLImageMapAccessible.cpp b/accessible/src/html/nsHTMLImageMapAccessible.cpp index c73839002b9..79753056523 100644 --- a/accessible/src/html/nsHTMLImageMapAccessible.cpp +++ b/accessible/src/html/nsHTMLImageMapAccessible.cpp @@ -40,6 +40,7 @@ #include "nsHTMLImageMapAccessible.h" #include "nsAccUtils.h" +#include "nsDocAccessible.h" #include "nsIDOMHTMLCollection.h" #include "nsIServiceManager.h" @@ -114,6 +115,8 @@ nsHTMLImageMapAccessible::CacheChildren() if (!mapAreas) return; + nsDocAccessible* document = GetDocAccessible(); + PRUint32 areaCount = 0; mapAreas->GetLength(&areaCount); @@ -124,21 +127,13 @@ nsHTMLImageMapAccessible::CacheChildren() return; nsCOMPtr areaContent(do_QueryInterface(areaNode)); - nsRefPtr areaAcc = + nsRefPtr area = new nsHTMLAreaAccessible(areaContent, mWeakShell); - if (!areaAcc) - return; - if (!areaAcc->Init()) { - areaAcc->Shutdown(); + if (!document->BindToDocument(area, nsAccUtils::GetRoleMapEntry(areaContent)) || + !AppendChild(area)) { return; } - - // We must respect ARIA on area elements (for the canvas map technique) - areaAcc->SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(areaContent)); - - if (!AppendChild(areaAcc)) - return; } } diff --git a/accessible/src/html/nsHTMLSelectAccessible.cpp b/accessible/src/html/nsHTMLSelectAccessible.cpp index 266507f7f90..14a468c10b9 100644 --- a/accessible/src/html/nsHTMLSelectAccessible.cpp +++ b/accessible/src/html/nsHTMLSelectAccessible.cpp @@ -692,21 +692,17 @@ nsHTMLComboboxAccessible::CacheChildren() if (!mListAccessible) { mListAccessible = new nsHTMLComboboxListAccessible(mParent, mContent, mWeakShell); - if (!mListAccessible) - return; // Initialize and put into cache. - if (!mListAccessible->Init()) { - mListAccessible->Shutdown(); + if (!GetDocAccessible()->BindToDocument(mListAccessible, nsnull)) return; - } } - AppendChild(mListAccessible); - - // Cache combobox option accessibles so that we build complete accessible tree - // for combobox. - mListAccessible->EnsureChildren(); + if (AppendChild(mListAccessible)) { + // Cache combobox option accessibles so that we build complete accessible + // tree for combobox. + mListAccessible->EnsureChildren(); + } } void diff --git a/accessible/src/html/nsHTMLTextAccessible.cpp b/accessible/src/html/nsHTMLTextAccessible.cpp index 3804e3c450a..d3e5f82ceef 100644 --- a/accessible/src/html/nsHTMLTextAccessible.cpp +++ b/accessible/src/html/nsHTMLTextAccessible.cpp @@ -259,8 +259,7 @@ nsHTMLLIAccessible:: nsBlockFrame* blockFrame = do_QueryFrame(GetFrame()); if (blockFrame && !blockFrame->BulletIsEmptyExternal()) { mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell); - if (mBulletAccessible) - mBulletAccessible->Init(); + GetDocAccessible()->BindToDocument(mBulletAccessible, nsnull); } } diff --git a/accessible/src/xul/nsXULColorPickerAccessible.cpp b/accessible/src/xul/nsXULColorPickerAccessible.cpp index b5792cb0f3b..87e41858a38 100644 --- a/accessible/src/xul/nsXULColorPickerAccessible.cpp +++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp @@ -41,6 +41,7 @@ #include "nsAccUtils.h" #include "nsAccTreeWalker.h" #include "nsCoreUtils.h" +#include "nsDocAccessible.h" #include "nsIDOMElement.h" @@ -171,5 +172,8 @@ nsXULColorPickerAccessible::CacheChildren() AppendChild(child); return; } + + // Unbind rejected accessibles from the document. + GetDocAccessible()->UnbindFromDocument(child); } } diff --git a/accessible/src/xul/nsXULFormControlAccessible.cpp b/accessible/src/xul/nsXULFormControlAccessible.cpp index 9106507e426..1f0375a5bbb 100644 --- a/accessible/src/xul/nsXULFormControlAccessible.cpp +++ b/accessible/src/xul/nsXULFormControlAccessible.cpp @@ -43,6 +43,7 @@ #include "nsAccUtils.h" #include "nsAccTreeWalker.h" #include "nsCoreUtils.h" +#include "nsDocAccessible.h" #include "nsRelUtils.h" // NOTE: alphabetically ordered @@ -222,6 +223,10 @@ nsXULButtonAccessible::CacheChildren() // for it. Ignore dropmarker button what is placed as a last child. buttonAccessible.swap(child); break; + + } else { + // Unbind rejected accessible from document. + GetDocAccessible()->UnbindFromDocument(child); } } diff --git a/accessible/src/xul/nsXULTreeAccessible.cpp b/accessible/src/xul/nsXULTreeAccessible.cpp index ca5c06e5a8b..cb323de1a0c 100644 --- a/accessible/src/xul/nsXULTreeAccessible.cpp +++ b/accessible/src/xul/nsXULTreeAccessible.cpp @@ -472,23 +472,21 @@ nsXULTreeAccessible::GetTreeItemAccessible(PRInt32 aRow) return nsnull; void *key = reinterpret_cast(aRow); - nsRefPtr accessible = mAccessibleCache.GetWeak(key); + nsAccessible* cachedTreeItem = mAccessibleCache.GetWeak(key); + if (cachedTreeItem) + return cachedTreeItem; - if (!accessible) { - accessible = CreateTreeItemAccessible(aRow); - if (!accessible) - return nsnull; + nsRefPtr treeItem = CreateTreeItemAccessible(aRow); + if (treeItem) { + if (mAccessibleCache.Put(key, treeItem)) { + if (GetDocAccessible()->BindToDocument(treeItem, nsnull)) + return treeItem; - if (!accessible->Init()) { - accessible->Shutdown(); - return nsnull; + mAccessibleCache.Remove(key); } - - if (!mAccessibleCache.Put(key, accessible)) - return nsnull; } - return accessible; + return nsnull; } void @@ -501,22 +499,21 @@ nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount) if (aCount > 0) return; + nsDocAccessible* document = GetDocAccessible(); + // Fire destroy event for removed tree items and delete them from caches. for (PRInt32 rowIdx = aRow; rowIdx < aRow - aCount; rowIdx++) { void* key = reinterpret_cast(rowIdx); - nsAccessible *accessible = mAccessibleCache.GetWeak(key); + nsAccessible* treeItem = mAccessibleCache.GetWeak(key); - if (accessible) { + if (treeItem) { nsRefPtr event = - new AccEvent(nsIAccessibleEvent::EVENT_HIDE, accessible); + new AccEvent(nsIAccessibleEvent::EVENT_HIDE, treeItem); nsEventShell::FireEvent(event); - // Shutdown and remove accessible from document cache and tree cache. - nsDocAccessible *docAccessible = GetDocAccessible(); - if (docAccessible) - docAccessible->ShutdownAccessible(accessible); - + // Unbind from document, shutdown and remove from tree cache. + document->UnbindFromDocument(treeItem); mAccessibleCache.Remove(key); } } @@ -534,14 +531,11 @@ nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount) for (PRInt32 rowIdx = newRowCount; rowIdx < oldRowCount; ++rowIdx) { void *key = reinterpret_cast(rowIdx); - nsAccessible *accessible = mAccessibleCache.GetWeak(key); - - if (accessible) { - // Shutdown and remove accessible from document cache and tree cache. - nsDocAccessible *docAccessible = GetDocAccessible(); - if (docAccessible) - docAccessible->ShutdownAccessible(accessible); + nsAccessible* treeItem = mAccessibleCache.GetWeak(key); + if (treeItem) { + // Unbind from document, shutdown and remove from tree cache. + document->UnbindFromDocument(treeItem); mAccessibleCache.Remove(key); } } diff --git a/accessible/src/xul/nsXULTreeGridAccessible.cpp b/accessible/src/xul/nsXULTreeGridAccessible.cpp index a91709e13f5..5450410e28b 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -41,6 +41,7 @@ #include "nsAccCache.h" #include "nsAccessibilityService.h" #include "nsAccUtils.h" +#include "nsDocAccessible.h" #include "nsEventShell.h" #include "nsITreeSelection.h" @@ -729,25 +730,23 @@ nsXULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn) NS_PRECONDITION(aColumn, "No tree column!"); void* key = static_cast(aColumn); - nsRefPtr accessible = mAccessibleCache.GetWeak(key); + nsAccessible* cachedCell = mAccessibleCache.GetWeak(key); + if (cachedCell) + return cachedCell; - if (!accessible) { - accessible = - new nsXULTreeGridCellAccessibleWrap(mContent, mWeakShell, this, mTree, - mTreeView, mRow, aColumn); - if (!accessible) - return nsnull; + nsRefPtr cell = + new nsXULTreeGridCellAccessibleWrap(mContent, mWeakShell, this, mTree, + mTreeView, mRow, aColumn); + if (cell) { + if (mAccessibleCache.Put(key, cell)) { + if (GetDocAccessible()->BindToDocument(cell, nsnull)) + return cell; - if (!accessible->Init()) { - accessible->Shutdown(); - return nsnull; + mAccessibleCache.Remove(key); } - - if (!mAccessibleCache.Put(key, accessible)) - return nsnull; } - return accessible; + return nsnull; } void