Philosophy behind ui/accessibility/platform

122 views
Skip to first unread message

Dominic Mazzoni

unread,
Oct 8, 2020, 5:56:43 PM10/8/20
to Chromium Accessibility
I'm sending this out because there were some questions recently about what belongs in ui/accessibility/platform and how it relates to content/browser/accessibility and the rest of the code. Some of this was covered by bugs or earlier design docs, but here's an explanation that's fully up-to-date with where we're at now.

In a sentence, ui/accessibility/platform is an abstraction of all of the platform accessibility APIs. All of the code that implements APIs for making your UI accessible on one specific platform like IAccessible, NSAccessibility, ATK, etc. go in ui/accessibility/platform and not elsewhere. None of the code specific to Chrome, web, or views belongs in ui/accessibility/platform.

The public interface is just two main classes:

1. AXPlatformNode - create one of those for every platform-specific accessible object you want. Call GetNativeViewAccessible() to get the actual object (IAccessible* on Windows, etc.)

2. AXPlatformNodeDelegate - implement your own subclass of that for every accessible object, and pass it to the AXPlatformNode constructor. Every time a platform API is called, it will call AXPlatformNodeDelegate to get the answer.

Nearly everything else in ui/accessibility/platform is not meant to be public. There are just a few other tiny things like the unique ID class that are public, but that's it.

What should ui/accessibility/platform depend on? Ideally very little else, just base and only simple structs and enums in ui/accessibility - notably, it should not depend on AXTree.

So, how does the idealized view of this compare with the reality? First, here's the good:

1. For the web, BrowserAccessibilityManager represents one web document. BrowserAccessibility represents one node in a document. BrowserAccessibility implements the AXPlatformNodeDelegate interface, and some of the subclasses of BrowserAccessibility own an AXPlatformNode. Great!

2. For Chrome's native UI, a View is one UI object. Each View owns a ViewAXPlatformNodeDelegate, which implements the AXPlatformNodeDelegate interface and owns an AXPlatformNode. Great!

3. Linux/ATK works exactly as intended! I believe 100% of the ATK code is found only in ui/accessibility/platform, and it works with both web and views!

4. AXSystemCaretWin is a pretty cool example of how useful the AXPlatformNode abstraction is. The system caret is a weird special case where we need a native accessible object as a one-off, it's not part of a tree and it's not either web or views. The AXSystemCaretWin code shows how easy it is to create an AXPlatformNode for that purpose, it's much easier than implementing the whole IAccessible* API. I wouldn't be surprised if someday we need this again.

5. We've been approached by another team that has a custom-drawn UI and wants to be accessible on the desktop. They'd like to reuse ui/accessibility/platform, which would be even more incentive to give it a cleaner public interface and maybe even spin it off as a separate library someday.

Now the bad:

1. Windows isn't quite fully migrated, but it's not too bad. BrowserAccessibilityComWin inherits from AXPlatformNodeWin and some of the Windows-specific interfaces are implemented there. That's bad because that code can't be used by Views. Ideally we should finish migrating it and delete BrowserAccessibilityComWin.

2. Mac isn't really migrated at all. AXPlatformNodeMac/AXPlatformNodeCocoa are only used for Views, and BrowserAccessibilityMac/BrowserAccessibilityCocoa are only used for web. We need to refactor those so that all of the Mac-specific code is moved to ui/accessibility/platform. To do it incrementally, we could have BrowserAccessibilityCocoa inherit from AXPlatformNodeCocoa, and then slowly move one interface at a time.

3. ui/accessibility/platform has a few interfaces that depend on AXTree and AXNode, and ideally they shouldn't. Instead I'd like all of that to be abstracted via AXPlatformNodeDelegate interfaces. Alternatively maybe we should have an AXPlatformTreeDelegate interface or something like that, but make it optional.

4. Android also isn't migrated. I think it'd be harder than Mac to migrate because the native interfaces are all Java. It's also fundamentally different because there isn't a separate persistent native object per-node like on every other platform.

5. We don't have as clean of a story yet on how to fire events. Right now Views and Web have their own event-firing code. As we finish migrating Views to use AXTree and AXEventGenerator we may be able to come up with a solution. Maybe we should add a "platform" counterpart to AXEventGenerator.

6. AXPlatformNode/AXPlatformNodeDelegate has some web-specific concepts. It's a bit of a leaky abstraction. Overall it's not too bad, and considering the whole reason we wrote it is for a web browser perhaps it's unavoidable. Still, as much as it's possible express concepts in a more generic way we should strive for that.

Not covered by above:

Alex has started migrating AccessibilityTreeFormatter into ui/accessibility/platform/inspect - I think it's a great fit, as it's essentially the counterpart - it provides an abstraction over calling the platform accessibility APIs, rather than implementing them, just for testing purposes.

Possible tasks:

1. The most important is, if you're writing new code, try to move things in the right direction based on this design!

2. Consider helping to migrate native accessibility code out of content/browser/accessibility and into ui/accessibility/platform

3. Consider creating a clear public interface for ui/accessibility/platform

4. Consider removing dependencies on AXNode and AXTree

5. Consider coming up with a design to simplify and abstract the platform event-firing code.

6. Consider helping to document everything captured in this email thread.

Reply all
Reply to author
Forward
0 new messages