diff --git a/accessible/base/EventQueue.cpp b/accessible/base/EventQueue.cpp index 20d9905117b4..b2b71ccebb63 100644 --- a/accessible/base/EventQueue.cpp +++ b/accessible/base/EventQueue.cpp @@ -83,7 +83,9 @@ bool EventQueue::PushNameOrDescriptionChange(AccEvent* aOrigEvent) { nsAutoString name; ENameValueFlag nameFlag = parent->Name(name); // If name is obtained from subtree, fire name change event. - if (nameFlag == eNameFromSubtree) { + // HTML file inputs always get part of their name from the subtree, even + // if the author provided a name. + if (nameFlag == eNameFromSubtree || parent->IsHTMLFileInput()) { RefPtr nameChangeEvent = new AccEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, parent); pushed |= PushEvent(nameChangeEvent); diff --git a/accessible/html/HTMLFormControlAccessible.cpp b/accessible/html/HTMLFormControlAccessible.cpp index 856b3632b603..a5baeefcbaf0 100644 --- a/accessible/html/HTMLFormControlAccessible.cpp +++ b/accessible/html/HTMLFormControlAccessible.cpp @@ -14,6 +14,7 @@ #include "Relation.h" #include "mozilla/a11y/Role.h" #include "States.h" +#include "TextLeafAccessible.h" #include "nsContentList.h" #include "mozilla/dom/HTMLInputElement.h" @@ -174,22 +175,6 @@ void HTMLButtonAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) { if (aIndex == eAction_Click) aName.AssignLiteral("press"); } -uint64_t HTMLButtonAccessible::State() { - uint64_t state = HyperTextAccessible::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()) { - uint64_t parentState = mParent->State(); - state |= parentState & (states::BUSY | states::REQUIRED | states::HASPOPUP | - states::INVALID); - } - - return state; -} - uint64_t HTMLButtonAccessible::NativeState() const { uint64_t state = HyperTextAccessible::NativeState(); @@ -467,55 +452,62 @@ HTMLFileInputAccessible::HTMLFileInputAccessible(nsIContent* aContent, DocAccessible* aDoc) : HyperTextAccessible(aContent, aDoc) { mType = eHTMLFileInputType; + mGenericTypes |= eButton; } -role HTMLFileInputAccessible::NativeRole() const { - // No specific role in AT APIs. We use GROUPING so that the label will be - // reported by screen readers when focus enters this control . - return roles::GROUPING; +role HTMLFileInputAccessible::NativeRole() const { return roles::PUSHBUTTON; } + +bool HTMLFileInputAccessible::IsAcceptableChild(nsIContent* aEl) const { + // File inputs are rendered using native anonymous children. However, we + // want to expose this as a button Accessible so that clients can pick up the + // name and description from the button they activate, rather than a + // container. We still expose the text leaf descendants so we can get the + // name of the Browse button and the file name. + return aEl->IsText(); } -nsresult HTMLFileInputAccessible::HandleAccEvent(AccEvent* aEvent) { - nsresult rv = HyperTextAccessible::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)) { - LocalAccessible* button = LocalChildAt(0); - if (button && button->Role() == roles::PUSHBUTTON) { - RefPtr childEvent = new AccStateChangeEvent( - button, event->GetState(), event->IsStateEnabled(), - event->FromUserInput()); - nsEventShell::FireEvent(childEvent); +ENameValueFlag HTMLFileInputAccessible::Name(nsString& aName) const { + ENameValueFlag flag = HyperTextAccessible::Name(aName); + if (flag == eNameFromSubtree) { + // The author didn't provide a name. We'll compute the name from our subtree + // below. + aName.Truncate(); + } else { + // The author provided a name. We do use that, but we also append our + // subtree text so the user knows this is a file chooser button and what + // file has been chosen. + if (aName.IsEmpty()) { + // Name computation is recursing, perhaps due to a wrapping