зеркало из https://github.com/mozilla/pjs.git
Bug 349885. GetAccessibleFor() doesn't look if ally nodes are allowed inside anon content. Patch by Alexander Surkov. r=aaronlev, sr=neil
This commit is contained in:
Родитель
77e17ead1b
Коммит
2fee238453
|
@ -54,7 +54,7 @@ interface nsIAccessNode;
|
|||
*
|
||||
* @status UNDER_REVIEW
|
||||
*/
|
||||
[scriptable, uuid(663CA4A8-D219-4000-925D-D8F66406B626)]
|
||||
[scriptable, uuid(2d8c1b1b-7a3f-4962-8a88-81ca019c11e9)]
|
||||
interface nsIAccessibleRetrieval : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -66,6 +66,30 @@ interface nsIAccessibleRetrieval : nsISupports
|
|||
*/
|
||||
nsIAccessible getAccessibleFor(in nsIDOMNode aNode);
|
||||
|
||||
/**
|
||||
* The same like getAccessibleFor method except it returns accessible only if
|
||||
* it is attached, i.e. accessible is certified to be a descendent of the root
|
||||
* accessible.
|
||||
*
|
||||
* @param aNode - the DOM node to get an accessible for.
|
||||
*
|
||||
* @return - the accessible for the given DOM node.
|
||||
*/
|
||||
nsIAccessible getAttachedAccessibleFor(in nsIDOMNode aNode);
|
||||
|
||||
/**
|
||||
* Return an DOM node that is relevant to attached accesible check. This
|
||||
* node is either from bindings chain if given node is anonymous and owner
|
||||
* binding denies accessible in anonymous content or given node (it's not
|
||||
* important whether it is accessible or not). This method doesn't create
|
||||
* accessible object for returned node.
|
||||
*
|
||||
* @param aNode - the DOM node to get relevant content node.
|
||||
*
|
||||
* @return - the DOM node for parent attached accessible
|
||||
*/
|
||||
nsIDOMNode getRelevantContentNodeFor(in nsIDOMNode aNode);
|
||||
|
||||
/**
|
||||
* Return an nsIAccessible for a DOM node in pres shell for this DOM window.
|
||||
* Create a new accessible of the appropriate type if necessary,
|
||||
|
|
|
@ -968,11 +968,12 @@ NS_IMETHODIMP nsAccessibilityService::GetCachedAccessNode(nsIDOMNode *aNode,
|
|||
* GetAccessibleFor - get an nsIAccessible from a DOM node
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
|
||||
nsIAccessible **aAccessible)
|
||||
NS_IMETHODIMP
|
||||
nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
// It's not ideal to call this -- it will assume shell #0
|
||||
// Some of our old test scripts still use it
|
||||
// We use presentation shell #0 because we assume that is presentation of
|
||||
// given node window.
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
if (content) {
|
||||
|
@ -988,6 +989,25 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
|
|||
return GetAccessibleInShell(aNode, presShell, aAccessible);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccessibilityService::GetAttachedAccessibleFor(nsIDOMNode *aNode,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
NS_ENSURE_ARG(aNode);
|
||||
NS_ENSURE_ARG_POINTER(aAccessible);
|
||||
|
||||
*aAccessible = nsnull;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> relevantNode;
|
||||
nsresult rv = GetRelevantContentNodeFor(aNode, getter_AddRefs(relevantNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (relevantNode != aNode)
|
||||
return NS_OK;
|
||||
|
||||
return GetAccessibleFor(aNode, aAccessible);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWindow(nsIDOMNode *aNode,
|
||||
nsIDOMWindow *aWin,
|
||||
nsIAccessible **aAccessible)
|
||||
|
@ -1303,6 +1323,73 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode,
|
|||
return InitAccessible(newAcc, aAccessible);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccessibilityService::GetRelevantContentNodeFor(nsIDOMNode *aNode,
|
||||
nsIDOMNode **aRelevantNode)
|
||||
{
|
||||
// The method returns node that is relevant for attached accessible check.
|
||||
// Sometimes element that is XBL widget hasn't accessible children in
|
||||
// anonymous content. This method check whether given node can be accessible
|
||||
// by looking through all nested bindings that given node is anonymous for. If
|
||||
// there is XBL widget that deniedes to be accessible for given node then the
|
||||
// method returns that XBL widget otherwise it returns given node.
|
||||
|
||||
// For example, the algorithm allows us to handle following cases:
|
||||
// 1. xul:dialog element has buttons (like 'ok' and 'cancel') in anonymous
|
||||
// content. When node is dialog's button then we dialog's button since button
|
||||
// of xul:dialog is accessible anonymous node.
|
||||
// 2. xul:texbox has html:input in anonymous content. When given node is
|
||||
// html:input elmement then we return xul:textbox since xul:textbox doesn't
|
||||
// allow accessible nodes in anonymous content.
|
||||
// 3. xforms:input that is hosted in xul document contains xul:textbox
|
||||
// element. When given node is html:input or xul:textbox then we return
|
||||
// xforms:input element since xforms:input hasn't accessible anonymous
|
||||
// children.
|
||||
|
||||
NS_ENSURE_ARG(aNode);
|
||||
NS_ENSURE_ARG_POINTER(aRelevantNode);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
|
||||
if (content) {
|
||||
// Build stack of binding parents so we can walk it in reverse.
|
||||
nsIContent *bindingParent;
|
||||
nsCOMArray<nsIContent> bindingsStack;
|
||||
|
||||
for (bindingParent = content->GetBindingParent(); bindingParent != nsnull;
|
||||
bindingParent = bindingParent->GetBindingParent()) {
|
||||
bindingsStack.AppendObject(bindingParent);
|
||||
}
|
||||
|
||||
PRInt32 bindingsCount = bindingsStack.Count();
|
||||
for (PRInt32 index = bindingsCount - 1; index >= 0 ; index--) {
|
||||
bindingParent = bindingsStack[index];
|
||||
nsCOMPtr<nsIDOMNode> bindingNode(do_QueryInterface(bindingParent));
|
||||
if (bindingNode) {
|
||||
// Try to get an accessible by type since XBL widget can be accessible
|
||||
// only if it implements nsIAccessibleProvider interface.
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
rv = GetAccessibleByType(bindingNode, getter_AddRefs(accessible));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsPIAccessible> paccessible(do_QueryInterface(accessible));
|
||||
if (paccessible) {
|
||||
PRBool allowsAnonChildren = PR_FALSE;
|
||||
paccessible->GetAllowsAnonChildAccessibles(&allowsAnonChildren);
|
||||
if (!allowsAnonChildren) {
|
||||
NS_ADDREF(*aRelevantNode = bindingNode);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aRelevantNode = aNode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAccessibilityService::GetAccessibleByType(nsIDOMNode *aNode,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
|
|
|
@ -791,27 +791,24 @@ void nsRootAccessible::GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNo
|
|||
|
||||
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aEvent));
|
||||
|
||||
if (nsevent) {
|
||||
nsCOMPtr<nsIDOMEventTarget> domEventTarget;
|
||||
nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget));
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(domEventTarget));
|
||||
nsIContent *bindingParent;
|
||||
if (content && content->IsNodeOfType(nsINode::eHTML) &&
|
||||
(bindingParent = content->GetBindingParent()) != nsnull) {
|
||||
// Use binding parent when the event occurs in
|
||||
// anonymous HTML content.
|
||||
// This gets the following important cases correct:
|
||||
// 1. Inserted <dialog> buttons like OK, Cancel, Help.
|
||||
// 2. XUL menulists and comboboxes.
|
||||
// 3. The focused radio button in a group.
|
||||
CallQueryInterface(bindingParent, aTargetNode);
|
||||
NS_ASSERTION(*aTargetNode, "No target node for binding parent of anonymous event target");
|
||||
if (!nsevent)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> domEventTarget;
|
||||
nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget));
|
||||
nsCOMPtr<nsIDOMNode> eventTarget(do_QueryInterface(domEventTarget));
|
||||
if (!eventTarget)
|
||||
return;
|
||||
|
||||
nsIAccessibilityService* accService = GetAccService();
|
||||
if (accService) {
|
||||
nsresult rv = accService->GetRelevantContentNodeFor(eventTarget,
|
||||
aTargetNode);
|
||||
if (NS_SUCCEEDED(rv) && *aTargetNode)
|
||||
return;
|
||||
}
|
||||
if (domEventTarget) {
|
||||
CallQueryInterface(domEventTarget, aTargetNode);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aTargetNode = eventTarget);
|
||||
}
|
||||
|
||||
void nsRootAccessible::FireFocusCallback(nsITimer *aTimer, void *aClosure)
|
||||
|
|
|
@ -105,7 +105,8 @@
|
|||
var accService =
|
||||
Components.classes['@mozilla.org/accessibilityService;1']
|
||||
.getService(Components.interfaces.nsIAccessibilityService);
|
||||
return accService.getAccessibleFor(object);
|
||||
|
||||
return accService.getAttachedAccessibleFor(object);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -400,8 +400,10 @@ inDOMView::GetCellProperties(PRInt32 row, nsITreeColumn* col, nsISupportsArray *
|
|||
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
accService->GetAccessibleFor(node->node, getter_AddRefs(accessible));
|
||||
if (accessible)
|
||||
nsresult rv =
|
||||
accService->GetAttachedAccessibleFor(node->node,
|
||||
getter_AddRefs(accessible));
|
||||
if (NS_SUCCEEDED(rv) && accessible)
|
||||
properties->AppendElement(kAccessibleNodeAtom);
|
||||
}
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче