author | Alexander Surkov <surkov.alexander@gmail.com> |
Fri, 12 Nov 2010 14:00:55 -0500 | |
changeset 57413 | b22e3d33e8b1b60d13f01ab1a1d36546f62cbf22 |
parent 57412 | 81f4de31f19e0aeb2343b07b4c7398805c147606 |
child 57414 | 3e941917e221c347d9c0fb4be2601afc1f7d135b |
push id | 16913 |
push user | surkov.alexander@gmail.com |
push date | Fri, 12 Nov 2010 19:01:27 +0000 |
treeherder | mozilla-central@3e941917e221 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ginn.chen, davidb, blockingBetaN |
bugs | 545465 |
milestone | 2.0b8pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/accessible/src/base/nsAccDocManager.cpp +++ b/accessible/src/base/nsAccDocManager.cpp @@ -451,37 +451,38 @@ nsAccDocManager::CreateDocOrRootAccessib } if (!outerDocAcc) return nsnull; // We only create root accessibles for the true root, otherwise create a // doc accessible. nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell)); - nsDocAccessible *docAcc = isRootDoc ? + nsRefPtr<nsDocAccessible> 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; + // Bind the document accessible into tree. + if (!outerDocAcc->AppendChild(docAcc)) { + mDocAccessibleCache.Remove(aDocument); 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))) { + // 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); return docAcc; } ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -832,38 +832,16 @@ nsAccessibilityService::GetCachedAccessi nsAccessible *accessible = nsnull; while (!(accessible = GetCachedAccessible(currNode, weakShell)) && (currNode = currNode->GetNodeParent())); 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; if (!aContent || !nsCoreUtils::GetID(aContent, id) || id.IsEmpty()) { return PR_FALSE; } nsIAtom *relationAttrs[] = {nsAccessibilityAtoms::aria_labelledby, @@ -953,16 +931,23 @@ nsAccessibilityService::GetOrCreateAcces // frame or the node is not an area element then null is returned. // This setup will change when bug 135040 is fixed. nsAccessible* areaAcc = GetAreaAccessible(weakFrame.GetFrame(), aNode, aWeakShell); NS_IF_ADDREF(areaAcc); 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<nsAccessible> newAcc; if (content->IsNodeOfType(nsINode::eTEXT)) { // --- Create HTML for visible text frames --- nsIFrame* f = weakFrame.GetFrame(); if (f && f->IsEmpty()) { nsAutoString renderedWhitespace; f->GetRenderedText(&renderedWhitespace, nsnull, nsnull, 0, 1); @@ -971,17 +956,17 @@ nsAccessibilityService::GetOrCreateAcces if (aIsHidden) *aIsHidden = PR_TRUE; return nsnull; } } if (weakFrame.IsAlive()) { newAcc = weakFrame.GetFrame()->CreateAccessible(); - if (InitAccessible(newAcc, nsnull)) + if (docAcc->BindToDocument(newAcc, nsnull)) return newAcc.forget(); return nsnull; } return nsnull; } PRBool isHTML = content->IsHTML(); @@ -999,17 +984,17 @@ nsAccessibilityService::GetOrCreateAcces if (!name.IsEmpty()) { if (aIsHidden) *aIsHidden = PR_TRUE; return nsnull; } newAcc = new nsHyperTextAccessibleWrap(content, aWeakShell); - if (InitAccessible(newAcc, nsAccUtils::GetRoleMapEntry(aNode))) + if (docAcc->BindToDocument(newAcc, nsAccUtils::GetRoleMapEntry(aNode))) return newAcc.forget(); return nsnull; } nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode); if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation") && !content->IsFocusable()) { // For presentation only // Only create accessible for role of "presentation" if it is focusable -- @@ -1186,17 +1171,17 @@ nsAccessibilityService::GetOrCreateAcces newAcc = new nsHyperTextAccessibleWrap(content, aWeakShell); } else { // XUL, SVG, MathML etc. // Interesting generic non-HTML container newAcc = new nsAccessibleWrap(content, aWeakShell); } } - if (InitAccessible(newAcc, roleMapEntry)) + if (docAcc->BindToDocument(newAcc, roleMapEntry)) return newAcc.forget(); return nsnull; } //////////////////////////////////////////////////////////////////////////////// // nsAccessibilityService private PRBool @@ -1343,32 +1328,39 @@ nsAccessibilityService::GetAreaAccessibl return nsnull; nsCOMPtr<nsIDOMHTMLAreaElement> areaElmt = do_QueryInterface(aAreaNode); if (!areaElmt) return nsnull; // Try to get image map accessible from the global cache or create it // if failed. - nsRefPtr<nsAccessible> imageAcc = - GetCachedAccessible(aImageFrame->GetContent(), aWeakShell); - if (!imageAcc) { - imageAcc = CreateHTMLImageAccessible(aImageFrame->GetContent(), - aImageFrame->PresContext()->PresShell()); + nsRefPtr<nsAccessible> 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 <area> 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); } already_AddRefed<nsAccessible> nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent, nsIWeakReference* aWeakShell) { @@ -1766,17 +1758,17 @@ nsAccessible* nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible) { #ifdef MOZ_ACCESSIBILITY_ATK nsApplicationAccessible* applicationAcc = nsAccessNode::GetApplicationAccessible(); if (!applicationAcc) return nsnull; - nsNativeRootAccessibleWrap* nativeRootAcc = + nsRefPtr<nsNativeRootAccessibleWrap> nativeRootAcc = new nsNativeRootAccessibleWrap((AtkObject*)aAtkAccessible); if (!nativeRootAcc) return nsnull; if (applicationAcc->AppendChild(nativeRootAcc)) return nativeRootAcc; #endif
--- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -197,29 +197,16 @@ public: * @param aDOMNode [in] the DOM node to get an accessible for */ inline nsAccessible* GetCachedContainerAccessible(nsINode *aNode) { return aNode ? 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 * the accessible already exists, otherwise null. * * @param aNode [in] the DOM node to get an access node for * @param aPresShell [in] the presentation shell which contains layout info * for the DOM node
--- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -2616,29 +2616,16 @@ nsAccessible::AppendTextTo(nsAString& aT } return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // 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() { // Invalidate the child count and pointers to other accessibles, also make // sure none of its children point to this parent InvalidateChildren(); if (mParent) mParent->RemoveChild(this); @@ -2907,30 +2894,16 @@ nsAccessible::GetIndexOfEmbeddedChild(ns mEmbeddedObjCollector = new EmbeddedObjCollector(this); return mEmbeddedObjCollector ? mEmbeddedObjCollector->GetIndexAt(aChild) : -1; } 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 bool nsAccessible::IsHyperLink() { // Every embedded accessible within hypertext accessible implements // hyperlink interface.
--- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -108,17 +108,16 @@ public: NS_DECL_NSIACCESSIBLEHYPERLINK NS_DECL_NSIACCESSIBLESELECTABLE NS_DECL_NSIACCESSIBLEVALUE NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLE_IMPL_IID) ////////////////////////////////////////////////////////////////////////////// // nsAccessNode - virtual PRBool Init(); virtual void Shutdown(); ////////////////////////////////////////////////////////////////////////////// // Public methods /** * Returns the accessible name specified by ARIA. */ @@ -293,23 +292,16 @@ public: return mParent ? mParent->mChildren.SafeElementAt(mIndexInParent - 1, nsnull).get() : nsnull; } PRUint32 GetCachedChildCount() const { return mChildren.Length(); } nsAccessible* GetCachedChildAt(PRUint32 aIndex) const { return mChildren.ElementAt(aIndex); } 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 /** * Handle accessible event, i.e. process it, notifies observers and fires * platform specific event. */ virtual nsresult HandleAccEvent(AccEvent* aAccEvent);
--- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -594,41 +594,16 @@ nsDocAccessible::GetCachedAccessible(nsI nsAccessible* parent(accessible->GetCachedParent()); if (parent) parent->TestChildCache(accessible); #endif 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 PRBool nsDocAccessible::Init() { NS_LOG_ACCDOCCREATE_FOR("document initialize", mDocument, this) @@ -1340,16 +1315,65 @@ nsDocAccessible::GetCachedAccessibleByUn child = childDocument->GetCachedAccessibleByUniqueIDInSubtree(aUniqueID); if (child) return child; } 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, nsIContent* aEndNode, PRBool aIsInsert) { // Content change notification mostly are async, thus we can't detect whether // these actions are from user. This information is used to fire or do not @@ -1756,30 +1780,26 @@ nsDocAccessible::UncacheChildrenInSubtre if (aRoot->IsPrimaryForNode() && mNodeToAccessibleMap.Get(aRoot->GetNode()) == aRoot) mNodeToAccessibleMap.Remove(aRoot->GetNode()); } 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 // parent and as result doesn't remove itself from its children. PRUint32 count = aAccessible->GetCachedChildCount(); for (PRUint32 idx = 0, jdx = 0; idx < count; idx++) { nsAccessible* child = aAccessible->GetCachedChildAt(jdx); if (!child->IsBoundToParent()) { NS_ERROR("Parent refers to a child, child doesn't refer to parent!"); jdx++; } ShutdownChildrenInSubtree(child); } - ShutdownAccessible(aAccessible); + UnbindFromDocument(aAccessible); }
--- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -206,28 +206,28 @@ public: /** * Return the cached accessible by the given unique ID looking through * this and nested documents. */ nsAccessible* GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID); /** - * Cache the accessible. - * - * @param aAccessible [in] accessible to cache + * Initialize the newly created accessible and put it into document caches. * - * @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 * accessible events as result of the processing. */ void ProcessPendingEvent(AccEvent* aEvent); /**
--- a/accessible/src/html/nsHTMLImageMapAccessible.cpp +++ b/accessible/src/html/nsHTMLImageMapAccessible.cpp @@ -35,16 +35,17 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsHTMLImageMapAccessible.h" #include "nsAccUtils.h" +#include "nsDocAccessible.h" #include "nsIDOMHTMLCollection.h" #include "nsIServiceManager.h" #include "nsIDOMElement.h" #include "nsIDOMHTMLAreaElement.h" #include "nsIFrame.h" #include "nsIImageFrame.h" #include "nsIImageMap.h" @@ -109,41 +110,35 @@ nsHTMLImageMapAccessible::CacheChildren( if (!mMapElement) return; nsCOMPtr<nsIDOMHTMLCollection> mapAreas; mMapElement->GetAreas(getter_AddRefs(mapAreas)); if (!mapAreas) return; + nsDocAccessible* document = GetDocAccessible(); + PRUint32 areaCount = 0; mapAreas->GetLength(&areaCount); for (PRUint32 areaIdx = 0; areaIdx < areaCount; areaIdx++) { nsCOMPtr<nsIDOMNode> areaNode; mapAreas->Item(areaIdx, getter_AddRefs(areaNode)); if (!areaNode) return; nsCOMPtr<nsIContent> areaContent(do_QueryInterface(areaNode)); - nsRefPtr<nsAccessible> areaAcc = + nsRefPtr<nsAccessible> 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; } } //////////////////////////////////////////////////////////////////////////////// // nsHTMLAreaAccessible ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp +++ b/accessible/src/html/nsHTMLSelectAccessible.cpp @@ -687,31 +687,27 @@ nsHTMLComboboxAccessible::CacheChildren( nsIFrame *listFrame = comboFrame->GetDropDown(); if (!listFrame) return; 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 nsHTMLComboboxAccessible::Shutdown() { nsAccessibleWrap::Shutdown(); if (mListAccessible) {
--- a/accessible/src/html/nsHTMLTextAccessible.cpp +++ b/accessible/src/html/nsHTMLTextAccessible.cpp @@ -254,18 +254,17 @@ nsHTMLOutputAccessible::GetAttributesInt nsHTMLLIAccessible:: nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell) : nsHyperTextAccessibleWrap(aContent, aShell) { nsBlockFrame* blockFrame = do_QueryFrame(GetFrame()); if (blockFrame && !blockFrame->BulletIsEmptyExternal()) { mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell); - if (mBulletAccessible) - mBulletAccessible->Init(); + GetDocAccessible()->BindToDocument(mBulletAccessible, nsnull); } } NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLIAccessible, nsHyperTextAccessible) void nsHTMLLIAccessible::Shutdown() {
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp +++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp @@ -36,16 +36,17 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsXULColorPickerAccessible.h" #include "nsAccUtils.h" #include "nsAccTreeWalker.h" #include "nsCoreUtils.h" +#include "nsDocAccessible.h" #include "nsIDOMElement.h" //////////////////////////////////////////////////////////////////////////////// // nsXULColorPickerTileAccessible //////////////////////////////////////////////////////////////////////////////// @@ -166,10 +167,13 @@ nsXULColorPickerAccessible::CacheChildre while ((child = walker.GetNextChild())) { PRUint32 role = child->Role(); // Get an accessbile for menupopup or panel elements. if (role == nsIAccessibleRole::ROLE_ALERT) { AppendChild(child); return; } + + // Unbind rejected accessibles from the document. + GetDocAccessible()->UnbindFromDocument(child); } }
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp +++ b/accessible/src/xul/nsXULFormControlAccessible.cpp @@ -38,16 +38,17 @@ * ***** END LICENSE BLOCK ***** */ #include "nsXULFormControlAccessible.h" #include "nsAccessibilityAtoms.h" #include "nsAccUtils.h" #include "nsAccTreeWalker.h" #include "nsCoreUtils.h" +#include "nsDocAccessible.h" #include "nsRelUtils.h" // NOTE: alphabetically ordered #include "nsHTMLFormControlAccessible.h" #include "nsXULMenuAccessible.h" #include "nsIDOMHTMLInputElement.h" #include "nsIDOMNSEditableElement.h" #include "nsIDOMXULButtonElement.h" @@ -217,16 +218,20 @@ nsXULButtonAccessible::CacheChildren() // Get an accessbile for menupopup or panel elements. menupopupAccessible.swap(child); } else if (isMenuButton && role == nsIAccessibleRole::ROLE_PUSHBUTTON) { // Button type="menu-button" contains a real button. Get an accessible // 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); } } if (!menupopupAccessible) return; AppendChild(menupopupAccessible); if (buttonAccessible)
--- a/accessible/src/xul/nsXULTreeAccessible.cpp +++ b/accessible/src/xul/nsXULTreeAccessible.cpp @@ -467,61 +467,58 @@ nsXULTreeAccessible::GetTreeItemAccessib return nsnull; PRInt32 rowCount = 0; nsresult rv = mTreeView->GetRowCount(&rowCount); if (NS_FAILED(rv) || aRow >= rowCount) return nsnull; void *key = reinterpret_cast<void*>(aRow); - nsRefPtr<nsAccessible> accessible = mAccessibleCache.GetWeak(key); - - if (!accessible) { - accessible = CreateTreeItemAccessible(aRow); - if (!accessible) - return nsnull; + nsAccessible* cachedTreeItem = mAccessibleCache.GetWeak(key); + if (cachedTreeItem) + return cachedTreeItem; - if (!accessible->Init()) { - accessible->Shutdown(); - return nsnull; + nsRefPtr<nsAccessible> treeItem = CreateTreeItemAccessible(aRow); + if (treeItem) { + if (mAccessibleCache.Put(key, treeItem)) { + if (GetDocAccessible()->BindToDocument(treeItem, nsnull)) + return treeItem; + + mAccessibleCache.Remove(key); } - - if (!mAccessibleCache.Put(key, accessible)) - return nsnull; } - return accessible; + return nsnull; } void nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount) { if (IsDefunct()) return; // Do not invalidate the cache if rows have been inserted. 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<void*>(rowIdx); - nsAccessible *accessible = mAccessibleCache.GetWeak(key); + nsAccessible* treeItem = mAccessibleCache.GetWeak(key); - if (accessible) { + if (treeItem) { nsRefPtr<AccEvent> 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); } } // We dealt with removed tree items already however we may keep tree items // having row indexes greater than row count. We should remove these dead tree // items silently from caches. PRInt32 newRowCount = 0; @@ -529,24 +526,21 @@ nsXULTreeAccessible::InvalidateCache(PRI if (NS_FAILED(rv)) return; PRInt32 oldRowCount = newRowCount - aCount; for (PRInt32 rowIdx = newRowCount; rowIdx < oldRowCount; ++rowIdx) { void *key = reinterpret_cast<void*>(rowIdx); - nsAccessible *accessible = mAccessibleCache.GetWeak(key); + nsAccessible* treeItem = mAccessibleCache.GetWeak(key); - if (accessible) { - // Shutdown and remove accessible from document cache and tree cache. - nsDocAccessible *docAccessible = GetDocAccessible(); - if (docAccessible) - docAccessible->ShutdownAccessible(accessible); - + if (treeItem) { + // Unbind from document, shutdown and remove from tree cache. + document->UnbindFromDocument(treeItem); mAccessibleCache.Remove(key); } } } void nsXULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow, PRInt32 aStartCol, PRInt32 aEndCol)
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -36,16 +36,17 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsXULTreeGridAccessibleWrap.h" #include "nsAccCache.h" #include "nsAccessibilityService.h" #include "nsAccUtils.h" +#include "nsDocAccessible.h" #include "nsEventShell.h" #include "nsITreeSelection.h" //////////////////////////////////////////////////////////////////////////////// // nsXULTreeGridAccessible //////////////////////////////////////////////////////////////////////////////// @@ -724,35 +725,33 @@ nsXULTreeGridRowAccessible::GetChildCoun // nsXULTreeGridRowAccessible: nsXULTreeItemAccessibleBase implementation nsAccessible* nsXULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn) { NS_PRECONDITION(aColumn, "No tree column!"); void* key = static_cast<void*>(aColumn); - nsRefPtr<nsAccessible> 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<nsAccessible> 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 nsXULTreeGridRowAccessible::RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx) { nsCOMPtr<nsITreeColumns> treeColumns; mTree->GetColumns(getter_AddRefs(treeColumns));