diff --git a/core-aam/acacia/all_apis_example.html b/core-aam/acacia/all_apis_example.html
index 38e2e3cca5b031..5dc231526f14c8 100644
--- a/core-aam/acacia/all_apis_example.html
+++ b/core-aam/acacia/all_apis_example.html
@@ -20,6 +20,9 @@
else if (node.API == 'axapi') {
assert_equals(node.role, 'AXButton', 'AX API role');
}
+ else if (node.API == 'windows') {
+ assert_equals(node.msaa_role, 'ROLE_SYSTEM_PUSHBUTTON', 'MSAA Role');
+ }
else {
assert_unreached(`Unknown API: ${node.API}`)
}
diff --git a/resources/testdriver.js b/resources/testdriver.js
index ec892af499a9b5..ac3ed65bd039f3 100644
--- a/resources/testdriver.js
+++ b/resources/testdriver.js
@@ -1076,7 +1076,7 @@
* rejected in the cases of failures.
*/
get_accessibility_api_node: async function(dom_id) {
- return window.test_driver_internal.get_accessibility_api_node(dom_id)
+ return window.test_driver_internal.get_accessibility_api_node(dom_id, location.href)
.then((jsonresult) => {
return JSON.parse(jsonresult);
});
@@ -1270,7 +1270,7 @@
throw new Error("clear_device_posture() is not implemented by testdriver-vendor.js");
},
- async get_accessibility_api_node(dom_id) {
+ async get_accessibility_api_node(dom_id, url) {
throw new Error("get_accessibility_api_node() is not available.");
}
};
diff --git a/tools/wptrunner/wptrunner/executors/actions.py b/tools/wptrunner/wptrunner/executors/actions.py
index 90ae943ac25829..41c56585c70ce7 100644
--- a/tools/wptrunner/wptrunner/executors/actions.py
+++ b/tools/wptrunner/wptrunner/executors/actions.py
@@ -473,7 +473,8 @@ def __init__(self, logger, protocol):
def __call__(self, payload):
dom_id = payload["dom_id"]
- return self.protocol.platform_accessibility.get_accessibility_api_node(dom_id)
+ url = payload["url"]
+ return self.protocol.platform_accessibility.get_accessibility_api_node(dom_id, url)
actions = [ClickAction,
diff --git a/tools/wptrunner/wptrunner/executors/executoratspi.py b/tools/wptrunner/wptrunner/executors/executoratspi.py
index d92af192aedf58..feb2fb114fe951 100644
--- a/tools/wptrunner/wptrunner/executors/executoratspi.py
+++ b/tools/wptrunner/wptrunner/executors/executoratspi.py
@@ -109,7 +109,8 @@ def setup(self, product_name, logger):
f"Couldn't find browser {self.product_name} in accessibility API ATSPI. Accessibility API queries will not succeeded."
)
- def get_accessibility_api_node(self, dom_id):
+
+ def get_accessibility_api_node(self, dom_id, url):
if not self.root:
raise Exception(
f"Couldn't find browser {self.product_name} in accessibility API ATSPI. Did you turn on accessibility?"
diff --git a/tools/wptrunner/wptrunner/executors/executoraxapi.py b/tools/wptrunner/wptrunner/executors/executoraxapi.py
index f864cbfebb1754..54c4fea472b390 100644
--- a/tools/wptrunner/wptrunner/executors/executoraxapi.py
+++ b/tools/wptrunner/wptrunner/executors/executoraxapi.py
@@ -91,7 +91,7 @@ def setup(self, product_name):
raise Exception(f"Couldn't find application: {product_name}")
- def get_accessibility_api_node(self, dom_id):
+ def get_accessibility_api_node(self, dom_id, url):
tab = find_active_tab(self.root)
node = find_node(tab, "AXDOMIdentifier", dom_id)
if not node:
diff --git a/tools/wptrunner/wptrunner/executors/executorplatformaccessibility.py b/tools/wptrunner/wptrunner/executors/executorplatformaccessibility.py
index b707352e7ab26d..f7868dc4c16a92 100644
--- a/tools/wptrunner/wptrunner/executors/executorplatformaccessibility.py
+++ b/tools/wptrunner/wptrunner/executors/executorplatformaccessibility.py
@@ -5,18 +5,19 @@
linux = False
mac = False
+windows = False
if platform == "linux":
linux = True
from .executoratspi import *
if platform == "darwin":
mac = True
from .executoraxapi import *
-
+if platform == "win32":
+ windows = True
+ from .executorwindowsaccessibility import WindowsAccessibilityExecutorImpl
class PlatformAccessibilityProtocolPart(ProtocolPart):
"""Protocol part for platform accessibility introspection"""
- __metaclass__ = ABCMeta
-
name = "platform_accessibility"
def setup(self):
@@ -28,6 +29,9 @@ def setup(self):
if mac:
self.impl = AXAPIExecutorImpl()
self.impl.setup(self.product_name)
+ if windows:
+ self.impl = WindowsAccessibilityExecutorImpl()
+ self.impl.setup(self.product_name)
- def get_accessibility_api_node(self, dom_id):
- return self.impl.get_accessibility_api_node(dom_id)
+ def get_accessibility_api_node(self, dom_id, url):
+ return self.impl.get_accessibility_api_node(dom_id, url)
diff --git a/tools/wptrunner/wptrunner/executors/executorwindowsaccessibility.py b/tools/wptrunner/wptrunner/executors/executorwindowsaccessibility.py
new file mode 100644
index 00000000000000..bca19b40d82636
--- /dev/null
+++ b/tools/wptrunner/wptrunner/executors/executorwindowsaccessibility.py
@@ -0,0 +1,127 @@
+from ..executors.ia2.constants import *
+
+import json
+import sys
+import time
+
+import ctypes
+from ctypes import POINTER, byref
+from ctypes.wintypes import BOOL, HWND, LPARAM, POINT
+
+import comtypes.client
+from comtypes import COMError, IServiceProvider
+
+CHILDID_SELF = 0
+OBJID_CLIENT = -4
+
+user32 = ctypes.windll.user32
+oleacc = ctypes.oledll.oleacc
+oleaccMod = comtypes.client.GetModule("oleacc.dll")
+IAccessible = oleaccMod.IAccessible
+
+# CoCreateInstance of UIA also initializes IA2
+uiaMod = comtypes.client.GetModule("UIAutomationCore.dll")
+uiaClient = comtypes.CoCreateInstance(
+ uiaMod.CUIAutomation._reg_clsid_,
+ interface=uiaMod.IUIAutomation,
+ clsctx=comtypes.CLSCTX_INPROC_SERVER,
+)
+
+def accessible_object_from_window(hwnd):
+ p = POINTER(IAccessible)()
+ oleacc.AccessibleObjectFromWindow(
+ hwnd, OBJID_CLIENT, byref(IAccessible._iid_), byref(p)
+ )
+ return p
+
+def name_from_hwnd(hwnd):
+ MAX_CHARS = 257
+ buffer = ctypes.create_unicode_buffer(MAX_CHARS)
+ user32.GetWindowTextW(hwnd, buffer, MAX_CHARS)
+ return buffer.value
+
+def get_browser_hwnd(product_name):
+ found = []
+
+ @ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
+ def check_window_name(hwnd, lParam):
+ window_name = name_from_hwnd(hwnd)
+ if product_name not in window_name.lower():
+ # EnumWindows should continue enumerating
+ return True
+ found.append(hwnd)
+ # EnumWindows should stop enumerating (since we found the right window)
+ return False
+
+ user32.EnumWindows(check_window_name, LPARAM(0))
+ if not found:
+ raise LookupError(f"Couldn't find {product_name} HWND")
+ return found[0]
+
+def to_ia2(node):
+ service = node.QueryInterface(IServiceProvider)
+ return service.QueryService(IAccessible2._iid_, IAccessible2)
+
+def find_browser(product_name):
+ hwnd = get_browser_hwnd(product_name)
+ root = accessible_object_from_window(hwnd)
+ return to_ia2(root)
+
+def poll_for_tab(url, root):
+ tab = find_tab(url, root)
+ while not tab:
+ time.sleep(0.01)
+ tab = find_tab(url, root)
+ return tab
+
+def find_tab(url, root):
+ for i in range(1, root.accChildCount + 1):
+ child = to_ia2(root.accChild(i))
+ if child.accRole(CHILDID_SELF) == ROLE_SYSTEM_DOCUMENT:
+ if child.accValue(CHILDID_SELF) == url:
+ return child
+ # No need to search within documents.
+ return
+ descendant = find_tab(url, child)
+ if descendant:
+ return descendant
+
+def find_ia2_node(root, id):
+ id_attribute = f"id:{id};"
+ for i in range(1, root.accChildCount + 1):
+ child = to_ia2(root.accChild(i))
+ if child.attributes and id_attribute in child.attributes:
+ return child
+ descendant = find_ia2_node(child, id)
+ if descendant:
+ return descendant
+
+def serialize_node(node):
+ node_dictionary = {}
+ node_dictionary["API"] = "windows"
+
+ # MSAA properties
+ node_dictionary["name"] = node.accName(CHILDID_SELF)
+ node_dictionary["msaa_role"] = role_to_string[node.accRole(CHILDID_SELF)]
+ node_dictionary["msaa_states"] = get_msaa_state_list(node.accState(CHILDID_SELF))
+
+ # IAccessible2 properties
+ node_dictionary["ia2_role"] = role_to_string[node.role()]
+ node_dictionary["ia2_states"] = get_state_list(node.states)
+
+ return node_dictionary
+
+class WindowsAccessibilityExecutorImpl:
+ def setup(self, product_name):
+ self.product_name = product_name
+
+ def get_accessibility_api_node(self, dom_id, url):
+ self.root = find_browser(self.product_name)
+ if not self.root:
+ raise Exception(f"Couldn't find browser {self.product_name}.")
+
+ tab = poll_for_tab(url, self.root)
+ node = find_ia2_node(tab, dom_id)
+ if not node:
+ raise Exception(f"Couldn't find node with ID {dom_id}.")
+ return json.dumps(serialize_node(node))
diff --git a/tools/wptrunner/wptrunner/executors/ia2/constants.py b/tools/wptrunner/wptrunner/executors/ia2/constants.py
new file mode 100644
index 00000000000000..73b7ff2d3a7642
--- /dev/null
+++ b/tools/wptrunner/wptrunner/executors/ia2/constants.py
@@ -0,0 +1,344 @@
+import os
+import comtypes.client
+
+# Get IAccessible2 constants for helper functions below
+ia2Tlb = os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ "ia2_api_all.tlb",
+)
+ia2Mod = comtypes.client.GetModule(ia2Tlb)
+# Add to globals the many IAccessible2 constants. These will also be imported
+# when this file is imported.
+globals().update((k, getattr(ia2Mod, k)) for k in ia2Mod.__all__)
+
+# Some constants are not provided via oleacc, specifically those for MSAA
+ROLE_SYSTEM_TITLEBAR=1
+ROLE_SYSTEM_MENUBAR=2
+ROLE_SYSTEM_SCROLLBAR=3
+ROLE_SYSTEM_GRIP=4
+ROLE_SYSTEM_SOUND=5
+ROLE_SYSTEM_CURSOR=6
+ROLE_SYSTEM_CARET=7
+ROLE_SYSTEM_ALERT=8
+ROLE_SYSTEM_WINDOW=9
+ROLE_SYSTEM_CLIENT=10
+ROLE_SYSTEM_MENUPOPUP=11
+ROLE_SYSTEM_MENUITEM=12
+ROLE_SYSTEM_TOOLTIP=13
+ROLE_SYSTEM_APPLICATION=14
+ROLE_SYSTEM_DOCUMENT=15
+ROLE_SYSTEM_PANE=16
+ROLE_SYSTEM_CHART=17
+ROLE_SYSTEM_DIALOG=18
+ROLE_SYSTEM_BORDER=19
+ROLE_SYSTEM_GROUPING=20
+ROLE_SYSTEM_SEPARATOR=21
+ROLE_SYSTEM_TOOLBAR=22
+ROLE_SYSTEM_STATUSBAR=23
+ROLE_SYSTEM_TABLE=24
+ROLE_SYSTEM_COLUMNHEADER=25
+ROLE_SYSTEM_ROWHEADER=26
+ROLE_SYSTEM_COLUMN=27
+ROLE_SYSTEM_ROW=28
+ROLE_SYSTEM_CELL=29
+ROLE_SYSTEM_LINK=30
+ROLE_SYSTEM_HELPBALLOON=31
+ROLE_SYSTEM_CHARACTER=32
+ROLE_SYSTEM_LIST=33
+ROLE_SYSTEM_LISTITEM=34
+ROLE_SYSTEM_OUTLINE=35
+ROLE_SYSTEM_OUTLINEITEM=36
+ROLE_SYSTEM_PAGETAB=37
+ROLE_SYSTEM_PROPERTYPAGE=38
+ROLE_SYSTEM_INDICATOR=39
+ROLE_SYSTEM_GRAPHIC=40
+ROLE_SYSTEM_STATICTEXT=41
+ROLE_SYSTEM_TEXT=42
+ROLE_SYSTEM_PUSHBUTTON=43
+ROLE_SYSTEM_CHECKBUTTON=44
+ROLE_SYSTEM_RADIOBUTTON=45
+ROLE_SYSTEM_COMBOBOX=46
+ROLE_SYSTEM_DROPLIST=47
+ROLE_SYSTEM_PROGRESSBAR=48
+ROLE_SYSTEM_DIAL=49
+ROLE_SYSTEM_HOTKEYFIELD=50
+ROLE_SYSTEM_SLIDER=51
+ROLE_SYSTEM_SPINBUTTON=52
+ROLE_SYSTEM_DIAGRAM=53
+ROLE_SYSTEM_ANIMATION=54
+ROLE_SYSTEM_EQUATION=55
+ROLE_SYSTEM_BUTTONDROPDOWN=56
+ROLE_SYSTEM_BUTTONMENU=57
+ROLE_SYSTEM_BUTTONDROPDOWNGRID=58
+ROLE_SYSTEM_WHITESPACE=59
+ROLE_SYSTEM_PAGETABLIST=60
+ROLE_SYSTEM_CLOCK=61
+ROLE_SYSTEM_SPLITBUTTON=62
+ROLE_SYSTEM_IPADDRESS=63
+ROLE_SYSTEM_OUTLINEBUTTON=64
+
+role_to_string = {
+ ROLE_SYSTEM_TITLEBAR: "ROLE_SYSTEM_TITLEBAR",
+ ROLE_SYSTEM_MENUBAR: "ROLE_SYSTEM_MENUBAR",
+ ROLE_SYSTEM_SCROLLBAR: "ROLE_SYSTEM_SCROLLBAR",
+ ROLE_SYSTEM_GRIP: "ROLE_SYSTEM_GRIP",
+ ROLE_SYSTEM_SOUND: "ROLE_SYSTEM_SOUND",
+ ROLE_SYSTEM_CURSOR: "ROLE_SYSTEM_CURSOR",
+ ROLE_SYSTEM_CARET: "ROLE_SYSTEM_CARET",
+ ROLE_SYSTEM_ALERT: "ROLE_SYSTEM_ALERT",
+ ROLE_SYSTEM_WINDOW: "ROLE_SYSTEM_WINDOW",
+ ROLE_SYSTEM_CLIENT: "ROLE_SYSTEM_CLIENT",
+ ROLE_SYSTEM_MENUPOPUP: "ROLE_SYSTEM_MENUPOPUP",
+ ROLE_SYSTEM_MENUITEM: "ROLE_SYSTEM_MENUITEM",
+ ROLE_SYSTEM_TOOLTIP: "ROLE_SYSTEM_TOOLTIP",
+ ROLE_SYSTEM_APPLICATION: "ROLE_SYSTEM_APPLICATION",
+ ROLE_SYSTEM_DOCUMENT: "ROLE_SYSTEM_DOCUMENT",
+ ROLE_SYSTEM_PANE: "ROLE_SYSTEM_PANE",
+ ROLE_SYSTEM_CHART: "ROLE_SYSTEM_CHART",
+ ROLE_SYSTEM_DIALOG: "ROLE_SYSTEM_DIALOG",
+ ROLE_SYSTEM_BORDER: "ROLE_SYSTEM_BORDER",
+ ROLE_SYSTEM_GROUPING: "ROLE_SYSTEM_GROUPING",
+ ROLE_SYSTEM_SEPARATOR: "ROLE_SYSTEM_SEPARATOR",
+ ROLE_SYSTEM_TOOLBAR: "ROLE_SYSTEM_TOOLBAR",
+ ROLE_SYSTEM_STATUSBAR: "ROLE_SYSTEM_STATUSBAR",
+ ROLE_SYSTEM_TABLE: "ROLE_SYSTEM_TABLE",
+ ROLE_SYSTEM_COLUMNHEADER: "ROLE_SYSTEM_COLUMNHEADER",
+ ROLE_SYSTEM_ROWHEADER: "ROLE_SYSTEM_ROWHEADER",
+ ROLE_SYSTEM_COLUMN: "ROLE_SYSTEM_COLUMN",
+ ROLE_SYSTEM_ROW: "ROLE_SYSTEM_ROW",
+ ROLE_SYSTEM_CELL: "ROLE_SYSTEM_CEL",
+ ROLE_SYSTEM_LINK: "ROLE_SYSTEM_LINK",
+ ROLE_SYSTEM_HELPBALLOON: "ROLE_SYSTEM_HELPBALLOON",
+ ROLE_SYSTEM_CHARACTER: "ROLE_SYSTEM_CHARACTER",
+ ROLE_SYSTEM_LIST: "ROLE_SYSTEM_LIST",
+ ROLE_SYSTEM_LISTITEM: "ROLE_SYSTEM_LISTITEM",
+ ROLE_SYSTEM_OUTLINE: "ROLE_SYSTEM_OUTLINE",
+ ROLE_SYSTEM_OUTLINEITEM: "ROLE_SYSTEM_OUTLINEITEM",
+ ROLE_SYSTEM_PAGETAB: "ROLE_SYSTEM_PAGETAB",
+ ROLE_SYSTEM_PROPERTYPAGE: "ROLE_SYSTEM_PROPERTYPAGE",
+ ROLE_SYSTEM_INDICATOR: "ROLE_SYSTEM_INDICATOR",
+ ROLE_SYSTEM_GRAPHIC: "ROLE_SYSTEM_GRAPHIC",
+ ROLE_SYSTEM_STATICTEXT: "ROLE_SYSTEM_STATICTEXT",
+ ROLE_SYSTEM_TEXT: "ROLE_SYSTEM_TEXT",
+ ROLE_SYSTEM_PUSHBUTTON: "ROLE_SYSTEM_PUSHBUTTON",
+ ROLE_SYSTEM_CHECKBUTTON: "ROLE_SYSTEM_CHECKBUTTON",
+ ROLE_SYSTEM_RADIOBUTTON: "ROLE_SYSTEM_RADIOBUTTON",
+ ROLE_SYSTEM_COMBOBOX: "ROLE_SYSTEM_COMBOBOX",
+ ROLE_SYSTEM_DROPLIST: "ROLE_SYSTEM_DROPLIST",
+ ROLE_SYSTEM_PROGRESSBAR: "ROLE_SYSTEM_PROGRESSBAR",
+ ROLE_SYSTEM_DIAL: "ROLE_SYSTEM_DIAL",
+ ROLE_SYSTEM_HOTKEYFIELD: "ROLE_SYSTEM_HOTKEYFIELD",
+ ROLE_SYSTEM_SLIDER: "ROLE_SYSTEM_SLIDER",
+ ROLE_SYSTEM_SPINBUTTON: "ROLE_SYSTEM_SPINBUTTON",
+ ROLE_SYSTEM_DIAGRAM: "ROLE_SYSTEM_DIAGRAM",
+ ROLE_SYSTEM_ANIMATION: "ROLE_SYSTEM_ANIMATION",
+ ROLE_SYSTEM_EQUATION: "ROLE_SYSTEM_EQUATION",
+ ROLE_SYSTEM_BUTTONDROPDOWN: "ROLE_SYSTEM_BUTTONDROPDOWN",
+ ROLE_SYSTEM_BUTTONMENU: "ROLE_SYSTEM_BUTTONMENU",
+ ROLE_SYSTEM_BUTTONDROPDOWNGRID: "ROLE_SYSTEM_BUTTONDROPDOWNGRID",
+ ROLE_SYSTEM_WHITESPACE: "ROLE_SYSTEM_WHITESPACE",
+ ROLE_SYSTEM_PAGETABLIST: "ROLE_SYSTEM_PAGETABLIST",
+ ROLE_SYSTEM_CLOCK: "ROLE_SYSTEM_CLOCK",
+ ROLE_SYSTEM_SPLITBUTTON: "ROLE_SYSTEM_SPLITBUTTON",
+ ROLE_SYSTEM_IPADDRESS: "ROLE_SYSTEM_IPADDRESS",
+ ROLE_SYSTEM_OUTLINEBUTTON: "ROLE_SYSTEM_OUTLINEBUTTON",
+ IA2_ROLE_CANVAS: "IA2_ROLE_CANVAS",
+ IA2_ROLE_CAPTION: "IA2_ROLE_CAPTION",
+ IA2_ROLE_CHECK_MENU_ITEM: "IA2_ROLE_CHECK_MENU_ITEM",
+ IA2_ROLE_COLOR_CHOOSER: "IA2_ROLE_COLOR_CHOOSER",
+ IA2_ROLE_DATE_EDITOR: "IA2_ROLE_DATE_EDITOR",
+ IA2_ROLE_DESKTOP_ICON: "IA2_ROLE_DESKTOP_ICON",
+ IA2_ROLE_DESKTOP_PANE: "IA2_ROLE_DESKTOP_PANE",
+ IA2_ROLE_DIRECTORY_PANE: "IA2_ROLE_DIRECTORY_PANE",
+ IA2_ROLE_EDITBAR: "IA2_ROLE_EDITBAR",
+ IA2_ROLE_EMBEDDED_OBJECT: "IA2_ROLE_EMBEDDED_OBJECT",
+ IA2_ROLE_ENDNOTE: "IA2_ROLE_ENDNOTE",
+ IA2_ROLE_FILE_CHOOSER: "IA2_ROLE_FILE_CHOOSER",
+ IA2_ROLE_FONT_CHOOSER: "IA2_ROLE_FONT_CHOOSER",
+ IA2_ROLE_FOOTER: "IA2_ROLE_FOOTER",
+ IA2_ROLE_FOOTNOTE: "IA2_ROLE_FOOTNOTE",
+ IA2_ROLE_FORM: "IA2_ROLE_FORM",
+ IA2_ROLE_FRAME: "IA2_ROLE_FRAME",
+ IA2_ROLE_GLASS_PANE: "IA2_ROLE_GLASS_PANE",
+ IA2_ROLE_HEADER: "IA2_ROLE_HEADER",
+ IA2_ROLE_HEADING: "IA2_ROLE_HEADING",
+ IA2_ROLE_ICON: "IA2_ROLE_ICON",
+ IA2_ROLE_IMAGE_MAP: "IA2_ROLE_IMAGE_MAP",
+ IA2_ROLE_INPUT_METHOD_WINDOW: "IA2_ROLE_INPUT_METHOD_WINDOW",
+ IA2_ROLE_INTERNAL_FRAME: "IA2_ROLE_INTERNAL_FRAME",
+ IA2_ROLE_LABEL: "IA2_ROLE_LABEL",
+ IA2_ROLE_LAYERED_PANE: "IA2_ROLE_LAYERED_PANE",
+ IA2_ROLE_NOTE: "IA2_ROLE_NOTE",
+ IA2_ROLE_OPTION_PANE: "IA2_ROLE_OPTION_PANE",
+ IA2_ROLE_PAGE: "IA2_ROLE_PAGE",
+ IA2_ROLE_PARAGRAPH: "IA2_ROLE_PARAGRAPH",
+ IA2_ROLE_RADIO_MENU_ITEM: "IA2_ROLE_RADIO_MENU_ITEM",
+ IA2_ROLE_REDUNDANT_OBJECT: "IA2_ROLE_REDUNDANT_OBJECT",
+ IA2_ROLE_ROOT_PANE: "IA2_ROLE_ROOT_PANE",
+ IA2_ROLE_RULER: "IA2_ROLE_RULER",
+ IA2_ROLE_SCROLL_PANE: "IA2_ROLE_SCROLL_PANE",
+ IA2_ROLE_SECTION: "IA2_ROLE_SECTION",
+ IA2_ROLE_SHAPE: "IA2_ROLE_SHAPE",
+ IA2_ROLE_SPLIT_PANE: "IA2_ROLE_SPLIT_PANE",
+ IA2_ROLE_TEAR_OFF_MENU: "IA2_ROLE_TEAR_OFF_MENU",
+ IA2_ROLE_TERMINAL: "IA2_ROLE_TERMINAL",
+ IA2_ROLE_TEXT_FRAME: "IA2_ROLE_TEXT_FRAME",
+ IA2_ROLE_TOGGLE_BUTTON: "IA2_ROLE_TOGGLE_BUTTON",
+ IA2_ROLE_UNKNOWN: "IA2_ROLE_UNKNOWN",
+ IA2_ROLE_VIEW_PORT: "IA2_ROLE_VIEW_PORT",
+ IA2_ROLE_COMPLEMENTARY_CONTENT: "IA2_ROLE_COMPLEMENTARY_CONTENT",
+ IA2_ROLE_LANDMARK: "IA2_ROLE_LANDMARK",
+ IA2_ROLE_LEVEL_BAR: "IA2_ROLE_LEVEL_BAR",
+ IA2_ROLE_CONTENT_DELETION: "IA2_ROLE_CONTENT_DELETION",
+ IA2_ROLE_CONTENT_INSERTION: "IA2_ROLE_CONTENT_INSERTION",
+ IA2_ROLE_BLOCK_QUOTE: "IA2_ROLE_BLOCK_QUOTE",
+ IA2_ROLE_MARK: "IA2_ROLE_MARK",
+ IA2_ROLE_SUGGESTION: "IA2_ROLE_SUGGESTION",
+ IA2_ROLE_COMMENT: "IA2_ROLE_COMMENT"
+}
+
+STATE_SYSTEM_UNAVAILABLE = 0x00000001
+STATE_SYSTEM_SELECTED = 0x00000002
+STATE_SYSTEM_FOCUSED = 0x00000004
+STATE_SYSTEM_PRESSED = 0x00000008
+STATE_SYSTEM_CHECKED = 0x00000010
+STATE_SYSTEM_MIXED = 0x00000020
+STATE_SYSTEM_INDETERMINATE = STATE_SYSTEM_MIXED
+STATE_SYSTEM_READONLY = 0x00000040
+STATE_SYSTEM_HOTTRACKED = 0x00000080
+STATE_SYSTEM_DEFAULT = 0x00000100
+STATE_SYSTEM_EXPANDED = 0x00000200
+STATE_SYSTEM_COLLAPSED = 0x00000400
+STATE_SYSTEM_BUSY = 0x00000800
+STATE_SYSTEM_FLOATING = 0x00001000
+STATE_SYSTEM_MARQUEED = 0x00002000
+STATE_SYSTEM_ANIMATED = 0x00004000
+STATE_SYSTEM_INVISIBLE = 0x00008000
+STATE_SYSTEM_OFFSCREEN = 0x00010000
+STATE_SYSTEM_SIZEABLE = 0x00020000
+STATE_SYSTEM_MOVEABLE = 0x00040000
+STATE_SYSTEM_SELFVOICING = 0x00080000
+STATE_SYSTEM_FOCUSABLE = 0x00100000
+STATE_SYSTEM_SELECTABLE = 0x00200000
+STATE_SYSTEM_LINKED = 0x00400000
+STATE_SYSTEM_TRAVERSED = 0x00800000
+STATE_SYSTEM_MULTISELECTABLE = 0x01000000
+STATE_SYSTEM_EXTSELECTABLE = 0x02000000
+STATE_SYSTEM_ALERT_LOW = 0x04000000
+STATE_SYSTEM_ALERT_MEDIUM = 0x08000000
+STATE_SYSTEM_ALERT_HIGH = 0x10000000
+STATE_SYSTEM_PROTECTED = 0x20000000
+STATE_SYSTEM_HASPOPUP = 0x40000000
+STATE_SYSTEM_VALID = 0x3FFFFFFF
+
+def get_msaa_state_list(states):
+ state_strings = []
+ if states & STATE_SYSTEM_ALERT_HIGH:
+ state_strings.append("ALERT_HIGH")
+ if states & STATE_SYSTEM_ALERT_MEDIUM:
+ state_strings.append("ALERT_MEDIUM")
+ if states & STATE_SYSTEM_ALERT_LOW:
+ state_strings.append("ALERT_LOW")
+ if states & STATE_SYSTEM_ANIMATED:
+ state_strings.append("ANIMATED")
+ if states & STATE_SYSTEM_BUSY:
+ state_strings.append("BUSY")
+ if states & STATE_SYSTEM_CHECKED:
+ state_strings.append("CHECKED")
+ if states & STATE_SYSTEM_COLLAPSED:
+ state_strings.append("COLLAPSED")
+ if states & STATE_SYSTEM_DEFAULT:
+ state_strings.append("DEFAULT")
+ if states & STATE_SYSTEM_EXPANDED:
+ state_strings.append("EXPANDED")
+ if states & STATE_SYSTEM_EXTSELECTABLE:
+ state_strings.append("EXTSELECTABLE")
+ if states & STATE_SYSTEM_FLOATING:
+ state_strings.append("FLOATING")
+ if states & STATE_SYSTEM_FOCUSABLE:
+ state_strings.append("FOCUSABLE")
+ if states & STATE_SYSTEM_FOCUSED:
+ state_strings.append("FOCUSED")
+ if states & STATE_SYSTEM_HASPOPUP:
+ state_strings.append("HASPOPUP")
+ if states & STATE_SYSTEM_HOTTRACKED:
+ state_strings.append("HOTTRACKED")
+ if states & STATE_SYSTEM_INVISIBLE:
+ state_strings.append("INVISIBLE")
+ if states & STATE_SYSTEM_LINKED:
+ state_strings.append("LINKED")
+ if states & STATE_SYSTEM_MARQUEED:
+ state_strings.append("MARQUEED")
+ if states & STATE_SYSTEM_MIXED:
+ state_strings.append("MIXED")
+ if states & STATE_SYSTEM_MOVEABLE:
+ state_strings.append("MOVEABLE")
+ if states & STATE_SYSTEM_MULTISELECTABLE:
+ state_strings.append("MULTISELECTABLE")
+ if states & STATE_SYSTEM_OFFSCREEN:
+ state_strings.append("OFFSCREEN")
+ if states & STATE_SYSTEM_PRESSED:
+ state_strings.append("PRESSED")
+ if states & STATE_SYSTEM_PROTECTED:
+ state_strings.append("PROTECTED")
+ if states & STATE_SYSTEM_READONLY:
+ state_strings.append("READONLY")
+ if states & STATE_SYSTEM_SELECTABLE:
+ state_strings.append("SELECTABLE")
+ if states & STATE_SYSTEM_SELECTED:
+ state_strings.append("SELECTED")
+ if states & STATE_SYSTEM_SELFVOICING:
+ state_strings.append("SELFVOICING")
+ if states & STATE_SYSTEM_SIZEABLE:
+ state_strings.append("SIZEABLE")
+ if states & STATE_SYSTEM_TRAVERSED:
+ state_strings.append("TRAVERSED")
+ if states & STATE_SYSTEM_UNAVAILABLE:
+ state_strings.append("UNAVAILABLE")
+
+ return state_strings
+
+def get_state_list(states):
+ state_strings = []
+ if states & IA2_STATE_ACTIVE:
+ state_strings.append("ACTIVE")
+ if states & IA2_STATE_ARMED:
+ state_strings.append("ARMED")
+ if states & IA2_STATE_CHECKABLE:
+ state_strings.append("CHECKABLE")
+ if states & IA2_STATE_DEFUNCT:
+ state_strings.append("DEFUNCT")
+ if states & IA2_STATE_EDITABLE:
+ state_strings.append("EDITABLE")
+ if states & IA2_STATE_HORIZONTAL:
+ state_strings.append("HORIZONTAL")
+ if states & IA2_STATE_ICONIFIED:
+ state_strings.append("ICONIFIED")
+ if states & IA2_STATE_INVALID_ENTRY:
+ state_strings.append("INVALID_ENTRY")
+ if states & IA2_STATE_MANAGES_DESCENDANTS:
+ state_strings.append("MANAGES_DESCENDANTS")
+ if states & IA2_STATE_MODAL:
+ state_strings.append("MODAL")
+ if states & IA2_STATE_MULTI_LINE:
+ state_strings.append("MULTI_LINE")
+ if states & IA2_STATE_OPAQUE:
+ state_strings.append("OPAQUE")
+ if states & IA2_STATE_PINNED:
+ state_strings.append("PINNED")
+ if states & IA2_STATE_REQUIRED:
+ state_strings.append("REQUIRED")
+ if states & IA2_STATE_SELECTABLE_TEXT:
+ state_strings.append("SELECTABLE_TEXT")
+ if states & IA2_STATE_SINGLE_LINE:
+ state_strings.append("SINGLE_LINE")
+ if states & IA2_STATE_STALE:
+ state_strings.append("STALE")
+ if states & IA2_STATE_SUPPORTS_AUTOCOMPLETION:
+ state_strings.append("SUPPORTS_AUTOCOMPLETION")
+ if states & IA2_STATE_TRANSIENT:
+ state_strings.append("TRANSIENT")
+ if states & IA2_STATE_VERTICAL:
+ state_strings.append("VERTICAL")
+
+ return state_strings
diff --git a/tools/wptrunner/wptrunner/executors/ia2/ia2_api_all.tlb b/tools/wptrunner/wptrunner/executors/ia2/ia2_api_all.tlb
new file mode 100644
index 00000000000000..449c10b258dd7b
Binary files /dev/null and b/tools/wptrunner/wptrunner/executors/ia2/ia2_api_all.tlb differ
diff --git a/tools/wptrunner/wptrunner/testdriver-extra.js b/tools/wptrunner/wptrunner/testdriver-extra.js
index e80c3ecb3e31e8..9a5880b17a4713 100644
--- a/tools/wptrunner/wptrunner/testdriver-extra.js
+++ b/tools/wptrunner/wptrunner/testdriver-extra.js
@@ -336,7 +336,7 @@
return create_action("clear_device_posture", {context});
};
- window.test_driver_internal.get_accessibility_api_node = function(dom_id) {
- return create_action("get_accessibility_api_node", {dom_id});
+ window.test_driver_internal.get_accessibility_api_node = function(dom_id, url) {
+ return create_action("get_accessibility_api_node", {dom_id, url});
};
})();