Preload accessibility framework if not already loaded
Summary: It looks like there are some edge cases when app did not load private accessibility framework (probably if it never set any accessibility values?) This diff makes calls to accessibility hierarchy safer and ensures to preload framework if available Reviewed By: lblasa Differential Revision: D49501064 fbshipit-source-id: b46216b58bf6c9c63f900e199fea035e3262afb2
This commit is contained in:
committed by
Facebook GitHub Bot
parent
947cc819e3
commit
21d86c09af
@@ -8,6 +8,7 @@
|
|||||||
#if FB_SONARKIT_ENABLED
|
#if FB_SONARKIT_ENABLED
|
||||||
|
|
||||||
#import "NSArray+Foundation.h"
|
#import "NSArray+Foundation.h"
|
||||||
|
#import "UIDAllyTraversal.h"
|
||||||
#import "UIDInitEvent+Foundation.h"
|
#import "UIDInitEvent+Foundation.h"
|
||||||
#import "UIDTraversalMode.h"
|
#import "UIDTraversalMode.h"
|
||||||
|
|
||||||
@@ -20,12 +21,15 @@ FB_LINKABLE(UIDInitEvent_Foundation)
|
|||||||
@"frameworkEventMetadata" : self.frameworkEventMetadata
|
@"frameworkEventMetadata" : self.frameworkEventMetadata
|
||||||
? [self.frameworkEventMetadata toFoundation]
|
? [self.frameworkEventMetadata toFoundation]
|
||||||
: @[],
|
: @[],
|
||||||
@"supportedTraversalModes" : @[
|
@"supportedTraversalModes" : UIDAllyTraversal.isSupported ? @[
|
||||||
NSStringFromUIDTraversalMode(UIDTraversalModeViewHierarchy),
|
NSStringFromUIDTraversalMode(UIDTraversalModeViewHierarchy),
|
||||||
NSStringFromUIDTraversalMode(UIDTraversalModeAccessibilityHierarchy),
|
NSStringFromUIDTraversalMode(UIDTraversalModeAccessibilityHierarchy),
|
||||||
|
] : @[
|
||||||
|
NSStringFromUIDTraversalMode(UIDTraversalModeViewHierarchy),
|
||||||
],
|
],
|
||||||
@"currentTraversalMode" :
|
@"currentTraversalMode" : NSStringFromUIDTraversalMode(
|
||||||
NSStringFromUIDTraversalMode(self.currentTraversalMode),
|
UIDAllyTraversal.isSupported ? self.currentTraversalMode
|
||||||
|
: UIDTraversalModeViewHierarchy),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@interface UIDAllyTraversal : NSObject
|
@interface UIDAllyTraversal : NSObject
|
||||||
|
|
||||||
|
@property(nonatomic, class, readonly, getter=isSupported) BOOL supported;
|
||||||
|
|
||||||
- (instancetype)initWithDescriptorRegister:
|
- (instancetype)initWithDescriptorRegister:
|
||||||
(UIDDescriptorRegister*)descriptorRegister;
|
(UIDDescriptorRegister*)descriptorRegister;
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,13 @@
|
|||||||
UIDDescriptorRegister* _descriptorRegister;
|
UIDDescriptorRegister* _descriptorRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isSupported {
|
||||||
|
return _loadAccessibilityFramework() &&
|
||||||
|
[UIApplication.sharedApplication
|
||||||
|
respondsToSelector:@selector
|
||||||
|
(_accessibilityLeafDescendantsWithOptions:)];
|
||||||
|
}
|
||||||
|
|
||||||
- (instancetype)initWithDescriptorRegister:
|
- (instancetype)initWithDescriptorRegister:
|
||||||
(UIDDescriptorRegister*)descriptorRegister {
|
(UIDDescriptorRegister*)descriptorRegister {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
@@ -41,10 +48,18 @@
|
|||||||
return @[];
|
return @[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_loadAccessibilityFramework()) {
|
||||||
|
return @[];
|
||||||
|
}
|
||||||
|
|
||||||
// create voice over representation of the app
|
// create voice over representation of the app
|
||||||
id options = [NSClassFromString(@"UIAccessibilityElementTraversalOptions")
|
id options = [NSClassFromString(@"UIAccessibilityElementTraversalOptions")
|
||||||
voiceOverOptionsIncludingElementsFromOpaqueProviders:YES
|
voiceOverOptionsIncludingElementsFromOpaqueProviders:YES
|
||||||
honorsGroups:NO];
|
honorsGroups:NO];
|
||||||
|
if (![application respondsToSelector:@selector
|
||||||
|
(_accessibilityLeafDescendantsWithOptions:)]) {
|
||||||
|
return @[];
|
||||||
|
}
|
||||||
NSArray<NSObject*>* const allyNodes = [[application
|
NSArray<NSObject*>* const allyNodes = [[application
|
||||||
_accessibilityLeafDescendantsWithOptions:options] mutableCopy];
|
_accessibilityLeafDescendantsWithOptions:options] mutableCopy];
|
||||||
|
|
||||||
@@ -78,6 +93,27 @@
|
|||||||
return uidNode;
|
return uidNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL _loadAccessibilityFramework(void) {
|
||||||
|
static BOOL isAccessibilityFrameworkLoaded;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
NSURL* const knownFrameworkUrl =
|
||||||
|
[NSBundle bundleForClass:UIApplication.class].bundleURL;
|
||||||
|
if (!knownFrameworkUrl) {
|
||||||
|
isAccessibilityFrameworkLoaded = NO;
|
||||||
|
} else {
|
||||||
|
NSURL* const accessibilityFrameworkUrl =
|
||||||
|
[knownFrameworkUrl.URLByDeletingLastPathComponent
|
||||||
|
.URLByDeletingLastPathComponent
|
||||||
|
URLByAppendingPathComponent:
|
||||||
|
@"PrivateFrameworks/UIAccessibility.framework"];
|
||||||
|
isAccessibilityFrameworkLoaded =
|
||||||
|
[[NSBundle bundleWithURL:accessibilityFrameworkUrl] load];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return isAccessibilityFrameworkLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
static NSString* _nameForNode(NSObject* node) {
|
static NSString* _nameForNode(NSObject* node) {
|
||||||
NSMutableArray* const parts = [NSMutableArray new];
|
NSMutableArray* const parts = [NSMutableArray new];
|
||||||
if (node.accessibilityLabel.length > 0) {
|
if (node.accessibilityLabel.length > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user