Bug 1743967 - Support async DoAction. r=Jamie

Now that we cache ActionCount, we can check for the absence of actions
and return false, or send an async message and return true.

Differential Revision: https://phabricator.services.mozilla.com/D135909
This commit is contained in:
Eitan Isaacson 2022-01-31 23:10:52 +00:00
parent ac8433cd7e
commit b494f3eab9
17 changed files with 71 additions and 25 deletions

View File

@ -18,13 +18,12 @@ using namespace mozilla::a11y;
extern "C" {
static gboolean doActionCB(AtkAction* aAction, gint aActionIndex) {
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
if (accWrap) {
return accWrap->DoAction(aActionIndex);
AtkObject* atkObject = ATK_OBJECT(aAction);
if (Accessible* acc = GetInternalObj(atkObject)) {
return acc->DoAction(aActionIndex);
}
RemoteAccessible* proxy = GetProxy(ATK_OBJECT(aAction));
return proxy && proxy->DoAction(aActionIndex);
return false;
}
static gint getActionCountCB(AtkAction* aAction) {

View File

@ -223,6 +223,11 @@ class Accessible {
TranslateString(name, aDescription);
}
/**
* Invoke the accessible action.
*/
virtual bool DoAction(uint8_t aIndex) const = 0;
// Type "is" methods
bool IsDoc() const { return HasGenericType(eDocument); }

View File

@ -508,10 +508,7 @@ class LocalAccessible : public nsISupports, public Accessible {
virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
/**
* Invoke the accessible action.
*/
virtual bool DoAction(uint8_t aIndex) const;
virtual bool DoAction(uint8_t aIndex) const override;
/**
* Return access key, such as Alt+D.

View File

@ -81,10 +81,12 @@ void HTMLLabelAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) {
}
bool HTMLLabelAccessible::DoAction(uint8_t aIndex) const {
if (aIndex != 0) return false;
if (aIndex == 0 && ActionCount()) {
DoCommand();
return true;
}
DoCommand();
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -170,6 +170,15 @@ mozilla::ipc::IPCResult DocAccessibleChildBase::RecvVerifyCache(
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessibleChildBase::RecvDoActionAsync(
const uint64_t& aID, const uint8_t& aIndex) {
if (LocalAccessible* acc = IdToAccessible(aID)) {
Unused << acc->DoAction(aIndex);
}
return IPC_OK();
}
LocalAccessible* DocAccessibleChildBase::IdToAccessible(
const uint64_t& aID) const {
if (!aID) return mDoc;

View File

@ -63,6 +63,9 @@ class DocAccessibleChildBase : public PDocAccessibleChild {
const uint64_t& aID, const uint64_t& aCacheDomain,
AccAttributes* aFields) override;
virtual mozilla::ipc::IPCResult RecvDoActionAsync(
const uint64_t& aID, const uint8_t& aIndex) override;
protected:
static void FlattenTree(LocalAccessible* aRoot,
nsTArray<LocalAccessible*>& aTree);

View File

@ -566,6 +566,16 @@ void RemoteAccessibleBase<Derived>::ActionNameAt(uint8_t aIndex,
VERIFY_CACHE(CacheDomain::Actions);
}
template <class Derived>
bool RemoteAccessibleBase<Derived>::DoAction(uint8_t aIndex) const {
if (ActionCount() < aIndex + 1) {
return false;
}
Unused << mDoc->SendDoActionAsync(mID, aIndex);
return true;
}
template <class Derived>
void RemoteAccessibleBase<Derived>::ARIAGroupPosition(
int32_t* aLevel, int32_t* aSetSize, int32_t* aPosInSet) const {

View File

@ -188,6 +188,8 @@ class RemoteAccessibleBase : public Accessible, public HyperTextAccessibleBase {
virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
virtual bool DoAction(uint8_t aIndex) const override;
// Methods that interact with content.
virtual void TakeFocus() const override;

View File

@ -216,7 +216,6 @@ bool UnselectAll();
void TakeSelection();
void SetSelected(bool aSelect);
bool DoAction(uint8_t aIndex);
KeyBinding AccessKey();
KeyBinding KeyboardShortcut();
void AtkKeyBinding(nsString& aBinding);

View File

@ -310,6 +310,7 @@ child:
async SetSelected(uint64_t aID, bool aSelected);
[Nested=inside_sync] sync DoAction(uint64_t aID, uint8_t aIndex) returns(bool aSuccess);
async DoActionAsync(uint64_t aID, uint8_t aIndex);
[Nested=inside_sync] sync ActionCount(uint64_t aID) returns(uint8_t aCount);
[Nested=inside_sync] sync ActionNameAt(uint64_t aID, uint8_t aIndex) returns(nsString aName);
[Nested=inside_sync] sync AccessKey(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask);

View File

@ -743,7 +743,11 @@ void RemoteAccessible::SetSelected(bool aSelect) {
Unused << mDoc->SendSetSelected(mID, aSelect);
}
bool RemoteAccessible::DoAction(uint8_t aIndex) {
bool RemoteAccessible::DoAction(uint8_t aIndex) const {
if (StaticPrefs::accessibility_cache_enabled_AtStartup()) {
return RemoteAccessibleBase<RemoteAccessible>::DoAction(aIndex);
}
bool success = false;
Unused << mDoc->SendDoAction(mID, aIndex, &success);
return success;

View File

@ -45,6 +45,8 @@ class RemoteAccessible : public RemoteAccessibleBase<RemoteAccessible> {
virtual int32_t LinkIndexAtOffset(uint32_t aOffset) override;
virtual bool DoAction(uint8_t aIndex) const override;
virtual uint8_t ActionCount() const override;
virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;

View File

@ -125,6 +125,8 @@ child:
*/
async VerifyCache(uint64_t aID, uint64_t aCacheDomain, AccAttributes aFields);
async DoActionAsync(uint64_t aID, uint8_t aIndex);
async __delete__();
};

View File

@ -123,6 +123,13 @@ addAccessibleTask(
let acc = findAccessibleChildByID(docAcc, "li_clickable1");
await untilCacheIs(() => acc.actionCount, 0, "li has no actions");
let thrown = false;
try {
acc.doAction(0);
} catch (e) {
thrown = true;
}
ok(thrown, "doAction should throw exception");
// Remove 'for' from label
await invokeContentTask(browser, [], () => {
@ -130,6 +137,14 @@ addAccessibleTask(
});
acc = findAccessibleChildByID(docAcc, "label1");
await untilCacheIs(() => acc.actionCount, 0, "label has no actions");
thrown = false;
try {
acc.doAction(0);
ok(false, "doAction should throw exception");
} catch (e) {
thrown = true;
}
ok(thrown, "doAction should throw exception");
// Add 'longdesc' to image
await invokeContentTask(browser, [], () => {

View File

@ -56,7 +56,7 @@ ia2AccessibleAction::nActions(long* aActionCount) {
STDMETHODIMP
ia2AccessibleAction::doAction(long aActionIndex) {
AccessibleWrap* acc = LocalAcc();
Accessible* acc = Acc();
if (!acc) return CO_E_OBJNOTCONNECTED;
uint8_t index = static_cast<uint8_t>(aActionIndex);

View File

@ -1681,11 +1681,8 @@ MsaaAccessible::accDoDefaultAction(
if (accessible) {
return accessible->accDoDefaultAction(kVarChildIdSelf);
}
if (mAcc->IsRemote()) {
return E_NOTIMPL; // XXX Not supported for RemoteAccessible yet.
}
return LocalAcc()->DoAction(0) ? S_OK : E_INVALIDARG;
return mAcc->DoAction(0) ? S_OK : E_INVALIDARG;
}
STDMETHODIMP

View File

@ -732,15 +732,14 @@ NS_IMETHODIMP
xpcAccessible::DoAction(uint8_t aIndex) {
if (!IntlGeneric()) return NS_ERROR_FAILURE;
if (RemoteAccessible* proxy = IntlGeneric()->AsRemote()) {
#if defined(XP_WIN)
if (IntlGeneric()->IsRemote() &&
!StaticPrefs::accessibility_cache_enabled_AtStartup()) {
return NS_ERROR_NOT_IMPLEMENTED;
#else
return proxy->DoAction(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
#endif
} else {
return Intl()->DoAction(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
}
#endif
return IntlGeneric()->DoAction(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
}
NS_IMETHODIMP