mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 606924 - deal with cached accessible tree only, r=davidb, a=blocking2.0final+
This commit is contained in:
parent
fed942f0b3
commit
6e1f0abc17
@ -559,15 +559,6 @@ nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
|
||||
document->RecreateAccessible(aContent);
|
||||
}
|
||||
|
||||
// nsAccessibilityService protected
|
||||
nsAccessible *
|
||||
nsAccessibilityService::GetCachedAccessible(nsINode *aNode,
|
||||
nsIWeakReference *aWeakShell)
|
||||
{
|
||||
nsDocAccessible *docAccessible = GetDocAccessible(aNode->GetOwnerDoc());
|
||||
return docAccessible ? docAccessible->GetCachedAccessible(aNode) : nsnull;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAccessibleRetrieval
|
||||
|
||||
@ -783,7 +774,7 @@ nsAccessibilityService::GetAccessibleInShell(nsINode* aNode,
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
|
||||
return GetAccessibleByRule(aNode, weakShell, eGetAccForNode);
|
||||
return GetAccessibleInWeakShell(aNode, weakShell);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -792,33 +783,20 @@ nsAccessibilityService::GetAccessibleInShell(nsINode* aNode,
|
||||
nsAccessible*
|
||||
nsAccessibilityService::GetAccessible(nsINode* aNode)
|
||||
{
|
||||
if (aNode) {
|
||||
nsCOMPtr<nsIWeakReference> weakShell(nsCoreUtils::GetWeakShellFor(aNode));
|
||||
if (weakShell)
|
||||
return GetAccessibleByRule(aNode, weakShell, eGetAccForNode);
|
||||
}
|
||||
return nsnull;
|
||||
nsDocAccessible* document = GetDocAccessible(aNode->GetOwnerDoc());
|
||||
return document ? document->GetCachedAccessible(aNode) : nsnull;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccessibilityService::GetCachedAccessibleOrContainer(nsINode* aNode)
|
||||
nsAccessibilityService::GetAccessibleOrContainer(nsINode* aNode,
|
||||
nsIWeakReference* aWeakShell)
|
||||
{
|
||||
if (!aNode)
|
||||
if (!aNode || !aNode->IsInDoc())
|
||||
return nsnull;
|
||||
|
||||
nsIDocument *document = aNode->GetCurrentDoc();
|
||||
if (!document)
|
||||
return nsnull;
|
||||
|
||||
nsIPresShell *presShell = document->GetShell();
|
||||
if (!presShell)
|
||||
return nsnull;
|
||||
|
||||
nsINode *currNode = aNode;
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
||||
|
||||
nsAccessible *accessible = nsnull;
|
||||
while (!(accessible = GetCachedAccessible(currNode, weakShell)) &&
|
||||
nsINode* currNode = aNode;
|
||||
nsAccessible* accessible = nsnull;
|
||||
while (!(accessible = GetAccessibleInWeakShell(currNode, aWeakShell)) &&
|
||||
(currNode = currNode->GetNodeParent()));
|
||||
|
||||
return accessible;
|
||||
@ -861,7 +839,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
*aIsSubtreeHidden = false;
|
||||
|
||||
// Check to see if we already have an accessible for this node in the cache.
|
||||
nsAccessible *cachedAccessible = GetCachedAccessible(aNode, aWeakShell);
|
||||
nsAccessible* cachedAccessible = GetAccessibleInWeakShell(aNode, aWeakShell);
|
||||
if (cachedAccessible) {
|
||||
NS_ADDREF(cachedAccessible);
|
||||
return cachedAccessible;
|
||||
@ -1237,69 +1215,6 @@ nsAccessibilityService::HasUniversalAriaProperty(nsIContent *aContent)
|
||||
nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_relevant);
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccessibilityService::GetAccessibleByRule(nsINode* aNode,
|
||||
nsIWeakReference* aWeakShell,
|
||||
EWhatAccToGet aWhatToGet)
|
||||
{
|
||||
if (!aNode || !aWeakShell)
|
||||
return nsnull;
|
||||
|
||||
if (aWhatToGet & eGetAccForNode) {
|
||||
nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell);
|
||||
if (cachedAcc && (cachedAcc->IsBoundToParent() || cachedAcc->IsDocument()))
|
||||
return cachedAcc;
|
||||
}
|
||||
|
||||
// Go up looking for the nearest accessible container having cached children.
|
||||
nsTArray<nsINode*> nodes;
|
||||
|
||||
nsINode* node = aNode;
|
||||
nsAccessible* cachedAcc = nsnull;
|
||||
while ((node = node->GetNodeParent())) {
|
||||
cachedAcc = GetCachedAccessible(node, aWeakShell);
|
||||
if (cachedAcc && cachedAcc->IsBoundToParent())
|
||||
break;
|
||||
|
||||
nodes.AppendElement(node);
|
||||
}
|
||||
|
||||
// Node is not in accessible document.
|
||||
if (!cachedAcc)
|
||||
return nsnull;
|
||||
|
||||
// If children of the cached accessible weren't initialized then go down to
|
||||
// the given node and create accessible tree.
|
||||
nsAccessible* containerAcc = cachedAcc;
|
||||
if (!cachedAcc->AreChildrenCached()) {
|
||||
cachedAcc->EnsureChildren();
|
||||
for (PRInt32 idx = nodes.Length() - 1; idx >= 0; idx--) {
|
||||
cachedAcc = GetCachedAccessible(nodes[idx], aWeakShell);
|
||||
if (cachedAcc) {
|
||||
cachedAcc->EnsureChildren();
|
||||
containerAcc = cachedAcc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the given node is accessible then it should be cached at this point.
|
||||
// Exception is an area element because area and imagemap nodes aren't in
|
||||
// the same parent chain.
|
||||
cachedAcc = GetCachedAccessible(aNode, aWeakShell);
|
||||
if (!cachedAcc && aNode->IsElement()) {
|
||||
nsIFrame* frame = aNode->AsElement()->GetPrimaryFrame();
|
||||
if (frame && frame->GetContent() != aNode)
|
||||
cachedAcc = GetAreaAccessible(frame, aNode, aWeakShell, &containerAcc);
|
||||
}
|
||||
|
||||
if ((aWhatToGet & eGetAccForNode) && cachedAcc)
|
||||
return cachedAcc;
|
||||
else if (aWhatToGet & eGetAccForContainer)
|
||||
return containerAcc;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccessibilityService::GetAreaAccessible(nsIFrame* aImageFrame,
|
||||
nsINode* aAreaNode,
|
||||
@ -1317,8 +1232,8 @@ nsAccessibilityService::GetAreaAccessible(nsIFrame* aImageFrame,
|
||||
|
||||
// Try to get image map accessible from the global cache or create it
|
||||
// if failed.
|
||||
nsRefPtr<nsAccessible> image = GetCachedAccessible(aImageFrame->GetContent(),
|
||||
aWeakShell);
|
||||
nsRefPtr<nsAccessible> image =
|
||||
GetAccessibleInWeakShell(aImageFrame->GetContent(), aWeakShell);
|
||||
if (!image) {
|
||||
image = CreateHTMLImageAccessible(aImageFrame->GetContent(),
|
||||
aImageFrame->PresContext()->PresShell());
|
||||
@ -1341,7 +1256,7 @@ nsAccessibilityService::GetAreaAccessible(nsIFrame* aImageFrame,
|
||||
// that they should be available in global cache.
|
||||
image->EnsureChildren();
|
||||
|
||||
return GetCachedAccessible(aAreaNode, aWeakShell);
|
||||
return GetAccessibleInWeakShell(aAreaNode, aWeakShell);
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
|
@ -163,57 +163,27 @@ public:
|
||||
inline nsAccessible* GetAccessibleInWeakShell(nsINode* aNode,
|
||||
nsIWeakReference* aWeakShell)
|
||||
{
|
||||
return GetAccessibleByRule(aNode, aWeakShell, eGetAccForNode);
|
||||
// XXX: weak shell is ignored until multiple shell documents are supported.
|
||||
return GetAccessible(aNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an accessible for the given DOM node or container accessible if
|
||||
* the node is not accessible.
|
||||
*/
|
||||
inline nsAccessible* GetAccessibleOrContainer(nsINode* aNode,
|
||||
nsIWeakReference* aWeakShell)
|
||||
{
|
||||
return GetAccessibleByRule(aNode, aWeakShell, eGetAccForNodeOrContainer);
|
||||
}
|
||||
nsAccessible* GetAccessibleOrContainer(nsINode* aNode,
|
||||
nsIWeakReference* aWeakShell);
|
||||
|
||||
/**
|
||||
* Return a container accessible for the given DOM node.
|
||||
*/
|
||||
inline nsAccessible* GetContainerAccessible(nsINode* aNode,
|
||||
nsIWeakReference* aWeakShell)
|
||||
{
|
||||
return GetAccessibleByRule(aNode, aWeakShell, eGetAccForContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return cached accessible for the given DOM node or cached container
|
||||
* accessible if there's no cached accessible for the given node.
|
||||
*/
|
||||
nsAccessible* GetCachedAccessibleOrContainer(nsINode* aNode);
|
||||
|
||||
/**
|
||||
* Return the first cached accessible parent of a DOM node.
|
||||
*
|
||||
* @param aDOMNode [in] the DOM node to get an accessible for
|
||||
*/
|
||||
inline nsAccessible* GetCachedContainerAccessible(nsINode *aNode)
|
||||
{
|
||||
return aNode ?
|
||||
GetCachedAccessibleOrContainer(aNode->GetNodeParent()) : nsnull;
|
||||
GetAccessibleOrContainer(aNode->GetNodeParent(), aWeakShell) : nsnull;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
nsAccessible *GetCachedAccessible(nsINode *aNode,
|
||||
nsIWeakReference *aShell);
|
||||
|
||||
private:
|
||||
// nsAccessibilityService creation is controlled by friend
|
||||
// NS_GetAccessibilityService, keep constructors private.
|
||||
@ -232,19 +202,6 @@ private:
|
||||
*/
|
||||
void Shutdown();
|
||||
|
||||
enum EWhatAccToGet {
|
||||
eGetAccForNode = 0x1,
|
||||
eGetAccForContainer = 0x2,
|
||||
eGetAccForNodeOrContainer = eGetAccForNode | eGetAccForContainer
|
||||
};
|
||||
|
||||
/**
|
||||
* Return accessible or accessible container for the given node in presshell.
|
||||
*/
|
||||
nsAccessible* GetAccessibleByRule(nsINode* aNode,
|
||||
nsIWeakReference* aWeakShell,
|
||||
EWhatAccToGet aWhatToGet);
|
||||
|
||||
/**
|
||||
* Return accessible for HTML area element associated with an image map.
|
||||
*
|
||||
|
@ -225,6 +225,15 @@ public:
|
||||
*/
|
||||
virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry);
|
||||
|
||||
/**
|
||||
* Update the children cache.
|
||||
*/
|
||||
inline bool UpdateChildren()
|
||||
{
|
||||
InvalidateChildren();
|
||||
return EnsureChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache children if necessary. Return true if the accessible is defunct.
|
||||
*/
|
||||
|
@ -1390,7 +1390,7 @@ nsDocAccessible::ContentInserted(nsIContent* aContainerNode,
|
||||
// Update the whole tree of this document accessible when the container is
|
||||
// null (document element is inserted or removed).
|
||||
nsAccessible* container = aContainerNode ?
|
||||
GetAccService()->GetCachedAccessibleOrContainer(aContainerNode) :
|
||||
GetAccService()->GetAccessibleOrContainer(aContainerNode, mWeakShell) :
|
||||
this;
|
||||
|
||||
mNotificationController->ScheduleContentInsertion(container,
|
||||
@ -1406,7 +1406,7 @@ nsDocAccessible::ContentRemoved(nsIContent* aContainerNode,
|
||||
// Update the whole tree of this document accessible when the container is
|
||||
// null (document element is removed).
|
||||
nsAccessible* container = aContainerNode ?
|
||||
GetAccService()->GetCachedAccessibleOrContainer(aContainerNode) :
|
||||
GetAccService()->GetAccessibleOrContainer(aContainerNode, mWeakShell) :
|
||||
this;
|
||||
|
||||
UpdateTree(container, aChildNode, PR_FALSE);
|
||||
@ -1452,7 +1452,7 @@ nsDocAccessible::RecreateAccessible(nsINode* aNode)
|
||||
}
|
||||
|
||||
// Get new accessible and fire show event.
|
||||
parent->InvalidateChildren();
|
||||
parent->UpdateChildren();
|
||||
|
||||
nsAccessible* newAccessible =
|
||||
GetAccService()->GetAccessibleInWeakShell(aNode, mWeakShell);
|
||||
@ -1492,12 +1492,11 @@ nsDocAccessible::NotifyOfCachingEnd(nsAccessible* aAccessible)
|
||||
for (PRUint32 idx = 0; idx < mInvalidationList.Length(); idx++) {
|
||||
nsIContent* content = mInvalidationList[idx];
|
||||
nsAccessible* container =
|
||||
GetAccService()->GetCachedContainerAccessible(content);
|
||||
container->InvalidateChildren();
|
||||
GetAccService()->GetContainerAccessible(content, mWeakShell);
|
||||
|
||||
// Make sure we keep children updated. While we're inside of caching loop
|
||||
// then we must exist it with cached children.
|
||||
container->EnsureChildren();
|
||||
container->UpdateChildren();
|
||||
}
|
||||
mInvalidationList.Clear();
|
||||
|
||||
@ -1860,16 +1859,14 @@ nsDocAccessible::ProcessContentInserted(nsAccessible* aContainer,
|
||||
// accessibles into accessible tree. We need to invalidate children even
|
||||
// there's no inserted accessibles in the end because accessible children
|
||||
// are created while parent recaches child accessibles.
|
||||
aContainer->InvalidateChildren();
|
||||
aContainer->UpdateChildren();
|
||||
|
||||
// The container might be changed, for example, because of the subsequent
|
||||
// overlapping content insertion (i.e. other content was inserted between this
|
||||
// inserted content and its container or the content was reinserted into
|
||||
// different container of unrelated part of tree). These cases result in
|
||||
// double processing, however generated events are coalesced and we don't
|
||||
// harm an AT. On the another hand container can be different because direct
|
||||
// container wasn't cached yet when we handled content insertion notification
|
||||
// and therefore we can't ignore the case when container has been changed.
|
||||
// harm an AT.
|
||||
// Theoretically the element might be not in tree at all at this point what
|
||||
// means there's no container.
|
||||
for (PRUint32 idx = 0; idx < aInsertedContent->Length(); idx++) {
|
||||
@ -1945,9 +1942,7 @@ nsDocAccessible::UpdateTreeInternal(nsAccessible* aContainer,
|
||||
if (aIsInsert && !node->GetPrimaryFrame())
|
||||
continue;
|
||||
|
||||
nsAccessible* accessible = aIsInsert ?
|
||||
GetAccService()->GetAccessibleInWeakShell(node, mWeakShell) :
|
||||
GetCachedAccessible(node);
|
||||
nsAccessible* accessible = GetCachedAccessible(node);
|
||||
|
||||
if (!accessible) {
|
||||
updateFlags |= UpdateTreeInternal(aContainer, node->GetFirstChild(),
|
||||
|
Loading…
Reference in New Issue
Block a user