mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 699017 - aria-required attribute on file input not read by JAWS, r=tbsaunde, marcoz, roc
This commit is contained in:
parent
8b5b5eab37
commit
d58d4c93bf
@ -347,6 +347,20 @@ struct nsARIAMap
|
||||
*/
|
||||
static nsAttributeCharacteristics gWAIUnivAttrMap[];
|
||||
static PRUint32 gWAIUnivAttrMapLength;
|
||||
|
||||
/**
|
||||
* Return accessible state from ARIA universal states applied to the given
|
||||
* element.
|
||||
*/
|
||||
static PRUint64 UniversalStatesFor(nsIContent* aContent)
|
||||
{
|
||||
PRUint64 state = 0;
|
||||
PRUint32 index = 0;
|
||||
while (nsStateMapEntry::MapToStates(aContent, &state, gWAIUnivStateMap[index]))
|
||||
index++;
|
||||
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -286,6 +286,16 @@ nsAccessibilityService::CreateHTMLCanvasAccessible(nsIContent* aContent,
|
||||
return accessible;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLFileInputAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
{
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
|
||||
nsAccessible* accessible = new nsHTMLFileInputAccessible(aContent, weakShell);
|
||||
NS_IF_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLImageAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
|
@ -91,6 +91,8 @@ public:
|
||||
CreateHTMLCheckboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLComboboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
already_AddRefed<nsAccessible>
|
||||
CreateHTMLFileInputAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
|
@ -1601,11 +1601,7 @@ void
|
||||
nsAccessible::ApplyARIAState(PRUint64* aState)
|
||||
{
|
||||
// Test for universal states first
|
||||
PRUint32 index = 0;
|
||||
while (nsStateMapEntry::MapToStates(mContent, aState,
|
||||
nsARIAMap::gWAIUnivStateMap[index])) {
|
||||
++ index;
|
||||
}
|
||||
*aState |= nsARIAMap::UniversalStatesFor(mContent);
|
||||
|
||||
if (mRoleMapEntry) {
|
||||
|
||||
|
@ -424,6 +424,8 @@ public:
|
||||
inline bool IsHyperText() const { return mFlags & eHyperTextAccessible; }
|
||||
nsHyperTextAccessible* AsHyperText();
|
||||
|
||||
inline bool IsHTMLFileInput() const { return mFlags & eHTMLFileInputAccessible; }
|
||||
|
||||
inline bool IsHTMLListItem() const { return mFlags & eHTMLListItemAccessible; }
|
||||
nsHTMLLIAccessible* AsHTMLListItem();
|
||||
|
||||
@ -645,12 +647,13 @@ protected:
|
||||
eComboboxAccessible = 1 << 5,
|
||||
eDocAccessible = 1 << 6,
|
||||
eHyperTextAccessible = 1 << 7,
|
||||
eHTMLListItemAccessible = 1 << 8,
|
||||
eListControlAccessible = 1 << 9,
|
||||
eMenuButtonAccessible = 1 << 10,
|
||||
eMenuPopupAccessible = 1 << 11,
|
||||
eRootAccessible = 1 << 12,
|
||||
eTextLeafAccessible = 1 << 13
|
||||
eHTMLFileInputAccessible = 1 << 8,
|
||||
eHTMLListItemAccessible = 1 << 9,
|
||||
eListControlAccessible = 1 << 10,
|
||||
eMenuButtonAccessible = 1 << 11,
|
||||
eMenuPopupAccessible = 1 << 12,
|
||||
eRootAccessible = 1 << 13,
|
||||
eTextLeafAccessible = 1 << 14
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -272,6 +272,25 @@ nsHTMLButtonAccessible::DoAction(PRUint8 aIndex)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLButtonAccessible::State()
|
||||
{
|
||||
PRUint64 state = nsHyperTextAccessibleWrap::State();
|
||||
if (state == states::DEFUNCT)
|
||||
return state;
|
||||
|
||||
// Inherit states from input@type="file" suitable for the button. Note,
|
||||
// no special processing for unavailable state since inheritance is supplied
|
||||
// other code paths.
|
||||
if (mParent && mParent->IsHTMLFileInput()) {
|
||||
PRUint64 parentState = mParent->State();
|
||||
state |= parentState & (states::BUSY | states::REQUIRED |
|
||||
states::HASPOPUP | states::INVALID);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLButtonAccessible::NativeState()
|
||||
{
|
||||
@ -477,7 +496,25 @@ nsHTMLTextFieldAccessible::ApplyARIAState(PRUint64* aState)
|
||||
nsHyperTextAccessibleWrap::ApplyARIAState(aState);
|
||||
|
||||
nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete);
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLTextFieldAccessible::State()
|
||||
{
|
||||
PRUint64 state = nsHyperTextAccessibleWrap::State();
|
||||
if (state & states::DEFUNCT)
|
||||
return state;
|
||||
|
||||
// Inherit states from input@type="file" suitable for the button. Note,
|
||||
// no special processing for unavailable state since inheritance is supplied
|
||||
// by other code paths.
|
||||
if (mParent && mParent->IsHTMLFileInput()) {
|
||||
PRUint64 parentState = mParent->State();
|
||||
state |= parentState & (states::BUSY | states::REQUIRED |
|
||||
states::HASPOPUP | states::INVALID);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
@ -612,6 +649,61 @@ nsHTMLTextFieldAccessible::ContainerWidget() const
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLGroupboxAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLFileInputAccessible::
|
||||
nsHTMLFileInputAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
|
||||
nsHyperTextAccessibleWrap(aContent, aShell)
|
||||
{
|
||||
mFlags |= eHTMLFileInputAccessible;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsHTMLFileInputAccessible::NativeRole()
|
||||
{
|
||||
// JAWS wants a text container, others don't mind. No specific role in
|
||||
// AT APIs.
|
||||
return nsIAccessibleRole::ROLE_TEXT_CONTAINER;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFileInputAccessible::HandleAccEvent(AccEvent* aEvent)
|
||||
{
|
||||
nsresult rv = nsHyperTextAccessibleWrap::HandleAccEvent(aEvent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Redirect state change events for inherited states to child controls. Note,
|
||||
// unavailable state is not redirected. That's a standard for unavailable
|
||||
// state handling.
|
||||
AccStateChangeEvent* event = downcast_accEvent(aEvent);
|
||||
if (event &&
|
||||
(event->GetState() == states::BUSY ||
|
||||
event->GetState() == states::REQUIRED ||
|
||||
event->GetState() == states::HASPOPUP ||
|
||||
event->GetState() == states::INVALID)) {
|
||||
nsAccessible* input = GetChildAt(0);
|
||||
if (input && input->Role() == nsIAccessibleRole::ROLE_ENTRY) {
|
||||
nsRefPtr<AccStateChangeEvent> childEvent =
|
||||
new AccStateChangeEvent(input, event->GetState(),
|
||||
event->IsStateEnabled(),
|
||||
(event->IsFromUserInput() ? eFromUserInput : eNoUserInput));
|
||||
nsEventShell::FireEvent(childEvent);
|
||||
}
|
||||
|
||||
nsAccessible* button = GetChildAt(1);
|
||||
if (button && button->Role() == nsIAccessibleRole::ROLE_PUSHBUTTON) {
|
||||
nsRefPtr<AccStateChangeEvent> childEvent =
|
||||
new AccStateChangeEvent(button, event->GetState(),
|
||||
event->IsStateEnabled(),
|
||||
(event->IsFromUserInput() ? eFromUserInput : eNoUserInput));
|
||||
nsEventShell::FireEvent(childEvent);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLGroupboxAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
// nsAccessible
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual PRUint32 NativeRole();
|
||||
virtual PRUint64 State();
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
// ActionAccessible
|
||||
@ -171,6 +172,7 @@ public:
|
||||
virtual void ApplyARIAState(PRUint64* aState);
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual PRUint32 NativeRole();
|
||||
virtual PRUint64 State();
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
// ActionAccessible
|
||||
@ -182,6 +184,19 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible for input@type="file" element.
|
||||
*/
|
||||
class nsHTMLFileInputAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsHTMLFileInputAccessible(nsIContent* aContent, nsIWeakReference* aShell);
|
||||
|
||||
// nsAccessible
|
||||
virtual PRUint32 NativeRole();
|
||||
virtual nsresult HandleAccEvent(AccEvent* aAccEvent);
|
||||
};
|
||||
|
||||
/**
|
||||
* Accessible for HTML fieldset element.
|
||||
*/
|
||||
|
@ -160,12 +160,8 @@ nsHyperTextAccessible::NativeRole()
|
||||
|
||||
// Treat block frames as paragraphs
|
||||
nsIFrame *frame = GetFrame();
|
||||
if (frame && frame->GetType() == nsGkAtoms::blockFrame &&
|
||||
frame->GetContent()->Tag() != nsGkAtoms::input) {
|
||||
// An html:input @type="file" is the only input that is exposed as a
|
||||
// blockframe. It must be exposed as ROLE_TEXT_CONTAINER for JAWS.
|
||||
if (frame && frame->GetType() == nsGkAtoms::blockFrame)
|
||||
return nsIAccessibleRole::ROLE_PARAGRAPH;
|
||||
}
|
||||
|
||||
return nsIAccessibleRole::ROLE_TEXT_CONTAINER; // In ATK this works
|
||||
}
|
||||
|
@ -1355,9 +1355,10 @@ function stateChangeChecker(aState, aIsExtraState, aIsEnabled,
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
is(event.state, aState, "Wrong state of the statechange event.");
|
||||
is(event.isExtraState(), aIsExtraState,
|
||||
"Wrong extra state bit of the statechange event.");
|
||||
isState(event.state, aState, aIsExtraState,
|
||||
"Wrong state of the statechange event.");
|
||||
is(event.isEnabled(), aIsEnabled,
|
||||
"Wrong state of statechange event state");
|
||||
|
||||
|
@ -70,12 +70,38 @@
|
||||
};
|
||||
}
|
||||
|
||||
function stateChangeOnFileInput(aID, aAttr, aValue,
|
||||
aState, aIsExtraState, aIsEnabled)
|
||||
{
|
||||
this.fileControlNode = getNode(aID);
|
||||
this.fileControl = getAccessible(this.fileControlNode);
|
||||
this.textEntry = this.fileControl.firstChild;
|
||||
this.browseButton = this.fileControl.lastChild;
|
||||
|
||||
this.invoke = function stateChangeOnFileInput_invoke()
|
||||
{
|
||||
this.fileControlNode.setAttribute(aAttr, aValue);
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.fileControl),
|
||||
new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.textEntry),
|
||||
new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.browseButton)
|
||||
];
|
||||
|
||||
this.getID = function stateChangeOnFileInput_getID()
|
||||
{
|
||||
return "inherited state change on file input on attribute '" + aAttr + "' change";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Do tests
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
// var gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true; // debug stuff
|
||||
|
||||
function doTests()
|
||||
{
|
||||
@ -88,6 +114,14 @@
|
||||
// invalid state change
|
||||
gQueue.push(new invalidInput("email"));
|
||||
|
||||
// file input inherited state changes
|
||||
gQueue.push(new stateChangeOnFileInput("file", "aria-busy", "true",
|
||||
STATE_BUSY, false, true));
|
||||
gQueue.push(new stateChangeOnFileInput("file", "aria-required", "true",
|
||||
STATE_REQUIRED, false, true));
|
||||
gQueue.push(new stateChangeOnFileInput("file", "aria-invalid", "true",
|
||||
STATE_INVALID, false, true));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -108,6 +142,11 @@
|
||||
title="Fire a11y event based on HTML5 constraint validation">
|
||||
Mozilla Bug 555728
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
|
||||
title="File input control should be propogate states to descendants">
|
||||
Mozilla Bug 699017
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
@ -120,6 +159,8 @@
|
||||
|
||||
<input id="email" type='email'>
|
||||
|
||||
<input id="file" type="file">
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -97,6 +97,14 @@
|
||||
// disabled, too. See bug 429285.
|
||||
testAriaDisabledTree("group");
|
||||
|
||||
// universal ARIA properties inherited from file input control
|
||||
var fileTextField = getAccessible("fileinput").firstChild;
|
||||
testStates(fileTextField,
|
||||
STATE_BUSY | STATE_UNAVAILABLE | STATE_REQUIRED | STATE_HASPOPUP | STATE_INVALID);
|
||||
var fileBrowseButton = getAccessible("fileinput").lastChild;
|
||||
testStates(fileBrowseButton,
|
||||
STATE_BUSY | STATE_UNAVAILABLE | STATE_REQUIRED | STATE_HASPOPUP | STATE_INVALID);
|
||||
|
||||
// offscreen test
|
||||
testStates("aria_offscreen_textbox", STATE_OFFSCREEN);
|
||||
|
||||
@ -171,6 +179,11 @@
|
||||
title="aria-orientation should be applied to separator and slider roles">
|
||||
Mozilla Bug 681674
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
|
||||
title="File input control should be propogate states to descendants">
|
||||
Mozilla Bug 699017
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
@ -215,7 +228,15 @@
|
||||
</div>
|
||||
<div role="slider" tabindex="0">A slider</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- universal ARIA properties should be inherited by text field of file input -->
|
||||
<input type="file" id="fileinput"
|
||||
aria-busy="true"
|
||||
aria-disabled="true"
|
||||
aria-required="true"
|
||||
aria-haspopup="true"
|
||||
aria-invalid="true">
|
||||
|
||||
<div id="offscreen_log" role="log" class="offscreen">
|
||||
<div id="aria_offscreen_textbox" role="textbox" aria-readonly="true">This text should be offscreen</div>
|
||||
</div>
|
||||
|
@ -36,6 +36,12 @@
|
||||
testStates("f_input", STATE_UNAVAILABLE);
|
||||
testStates("f_input_disabled", STATE_UNAVAILABLE);
|
||||
|
||||
// inherited from file control
|
||||
var fileTextField = getAccessible("file").firstChild;
|
||||
testStates(fileTextField, STATE_UNAVAILABLE | STATE_REQUIRED);
|
||||
var fileBrowseButton = getAccessible("file").lastChild;
|
||||
testStates(fileBrowseButton, STATE_UNAVAILABLE | STATE_REQUIRED);
|
||||
|
||||
/**
|
||||
* maxlength doesn't make the element invalid until bug 613016 and bug 613019
|
||||
* are fixed. Commenting out related lines and adding a todo to make sure
|
||||
@ -110,6 +116,11 @@
|
||||
title="Add accessibility support for @list on HTML input and for HTML datalist">
|
||||
Mozilla Bug 559766
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
|
||||
title="File input control should be propogate states to descendants">
|
||||
Mozilla Bug 699017
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
@ -146,6 +157,9 @@
|
||||
<input id="f_input_disabled" disabled>
|
||||
</fieldset>
|
||||
|
||||
<!-- inherited from input@type="file" -->
|
||||
<input id="file" type="file" required disabled>
|
||||
|
||||
<!-- invalid/valid -->
|
||||
<input id="maxlength" maxlength="1">
|
||||
<input id="maxlength2" maxlength="100" value="foo">
|
||||
|
@ -747,8 +747,8 @@ nsFileControlFrame::CreateAccessible()
|
||||
if (!accService)
|
||||
return nsnull;
|
||||
|
||||
return accService->CreateHyperTextAccessible(mContent,
|
||||
PresContext()->PresShell());
|
||||
return accService->CreateHTMLFileInputAccessible(mContent,
|
||||
PresContext()->PresShell());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user