tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 09aedb6aef474d6d27b27be1065d6f126fb6f044
parent ccd1be9f2f7645e5278dec84fed833540f4a5098
Author: Eitan Isaacson <eitan@monotonous.org>
Date:   Fri, 17 Oct 2025 05:30:07 +0000

Bug 1994030 - P2: Expose aria-actions via accessibilityCustomActions. r=morgan

Differential Revision: https://phabricator.services.mozilla.com/D268472

Diffstat:
Maccessible/mac/MOXAccessibleBase.h | 6++++++
Maccessible/mac/MOXAccessibleBase.mm | 10++++++++++
Maccessible/mac/MOXAccessibleProtocol.h | 3+++
Maccessible/mac/mozAccessible.h | 3+++
Maccessible/mac/mozAccessible.mm | 29+++++++++++++++++++++++++++++
Maccessible/mac/mozAccessibleProtocol.h | 2++
Maccessible/tests/browser/mac/browser.toml | 2++
Aaccessible/tests/browser/mac/browser_custom_actions.js | 39+++++++++++++++++++++++++++++++++++++++
8 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/accessible/mac/MOXAccessibleBase.h b/accessible/mac/MOXAccessibleBase.h @@ -79,6 +79,9 @@ inline id<mozAccessible> GetObjectOrRepresentedView(id<mozAccessible> aObject) { - (id)accessibilityFocusedUIElement; // override, final +- (NSArray*)accessibilityCustomActions; + +// override, final - (BOOL)isAccessibilityElement; // final @@ -97,6 +100,9 @@ inline id<mozAccessible> GetObjectOrRepresentedView(id<mozAccessible> aObject) { - (id)moxFocusedUIElement; // override +- (NSArray*)moxCustomActions; + +// override - (void)moxPostNotification:(NSString*)notification; // override diff --git a/accessible/mac/MOXAccessibleBase.mm b/accessible/mac/MOXAccessibleBase.mm @@ -390,6 +390,12 @@ mozilla::LogModule* GetMacAccessibilityLog() { NS_OBJC_END_TRY_BLOCK_RETURN(nil); } +- (id)accessibilityCustomActions { + NS_OBJC_BEGIN_TRY_BLOCK_RETURN; + return [self moxCustomActions]; + NS_OBJC_END_TRY_BLOCK_RETURN(nil); +} + - (BOOL)isAccessibilityElement { NS_OBJC_BEGIN_TRY_BLOCK_RETURN; @@ -586,6 +592,10 @@ mozilla::LogModule* GetMacAccessibilityLog() { return nil; } +- (NSArray*)moxCustomActions { + return nil; +} + #pragma mark - Private - (BOOL)isSelectorSupported:(SEL)selector { diff --git a/accessible/mac/MOXAccessibleProtocol.h b/accessible/mac/MOXAccessibleProtocol.h @@ -25,6 +25,9 @@ // Forwarded from accessibilityFocusedUIElement. - (id _Nullable)moxFocusedUIElement; +// Retrieve a list of custom actions. +- (NSArray* _Nullable)moxCustomActions; + // Sends a notification to any observing assistive applications. - (void)moxPostNotification:(NSString* _Nonnull)notification; diff --git a/accessible/mac/mozAccessible.h b/accessible/mac/mozAccessible.h @@ -188,6 +188,9 @@ enum CheckedState { - (NSArray*)moxCustomContent; // override +- (NSArray*)moxCustomActions; + +// override - (NSNumber*)moxEnabled; // override diff --git a/accessible/mac/mozAccessible.mm b/accessible/mac/mozAccessible.mm @@ -580,6 +580,35 @@ static bool ProvidesTitle(const Accessible* aAccessible, nsString& aName) { NS_OBJC_END_TRY_BLOCK_RETURN(nil); } +- (NSArray*)moxCustomActions { + if (@available(macOS 13.0, *)) { + NSMutableArray<NSAccessibilityCustomAction*>* customActions = + [[[NSMutableArray alloc] init] autorelease]; + Relation relatedActions( + mGeckoAccessible->RelationByType(RelationType::ACTION)); + while (Accessible* target = relatedActions.Next()) { + if (target->HasPrimaryAction()) { + // Any ACTION related accesibles should be considered a custom action. + mozAccessible* nativeTarget = GetNativeFromGeckoAccessible(target); + if (nativeTarget) { + nsAutoString name; + // Use the name of the target as the action name. + target->Name(name); + NSAccessibilityCustomAction* action = + [[NSAccessibilityCustomAction alloc] + initWithName:nsCocoaUtils::ToNSString(name) + target:nativeTarget + selector:@selector(moxPerformPress)]; + [customActions addObject:action]; + } + } + } + return customActions; + } + + return nil; +} + - (NSWindow*)moxWindow { NS_OBJC_BEGIN_TRY_BLOCK_RETURN; diff --git a/accessible/mac/mozAccessibleProtocol.h b/accessible/mac/mozAccessibleProtocol.h @@ -45,6 +45,8 @@ // currently focused UI element (possibly a child accessible) - (id)accessibilityFocusedUIElement; +- (NSArray*)accessibilityCustomActions; + /*** attributes ***/ // all supported attributes diff --git a/accessible/tests/browser/mac/browser.toml b/accessible/tests/browser/mac/browser.toml @@ -47,6 +47,8 @@ skip-if = ["os == 'mac' && os_version == '15.30' && arch == 'aarch64' && opt"] # ["browser_combobox.js"] +["browser_custom_actions.js"] + ["browser_description.js"] ["browser_details_summary.js"] diff --git a/accessible/tests/browser/mac/browser_custom_actions.js b/accessible/tests/browser/mac/browser_custom_actions.js @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* import-globals-from ../../mochitest/role.js */ +/* import-globals-from ../../mochitest/states.js */ +loadScripts( + { name: "role.js", dir: MOCHITESTS_DIR }, + { name: "states.js", dir: MOCHITESTS_DIR } +); + +// Test custom action +addAccessibleTask( + `<div id="container"> + <dialog aria-actions="btn" id="dlg" open> + Hello + <form method="dialog"> + <button id="btn">Close</button> + </form> + </dialog> + </div>`, + async (browser, accDoc) => { + let dialog = getNativeInterface(accDoc, "dlg"); + let actionNames = dialog.actionNames; + let customAction = actionNames.find(name => name.startsWith("Name:Close")); + ok(!!customAction, "Dialog should have a custom action"); + is( + dialog.getActionDescription(customAction), + "Close", + "Correct action description" + ); + + const reorder = waitForEvent(EVENT_REORDER, "container"); + dialog.performAction(customAction); + await reorder; + } +);