未验证 提交 5b10fa35 编写于 作者: D Darren Austin 提交者: GitHub

Guard against orphaned semantic objects from referencing dead accessibility bridge on iOS (#13857)

* Guard against orphaned semantic objects trying to reference a dead bridge on iOS.

* Switched back to a function instead of a macro for checking the bridge.

* Fixed some formatting issues.
上级 6bab64e6
......@@ -47,11 +47,25 @@ class AccessibilityBridge;
/**
* The accessibility bridge that this semantics object is attached to. This
* object may use the bridge to access contextual application information. A weak pointer is used
* because the platform view owns the accessibility bridge.
* object may use the bridge to access contextual application information. A weak
* pointer is used because the platform view owns the accessibility bridge.
* If you are referencing this property from an iOS callback, be sure to
* use `isAccessibilityBridgeActive` to protect against the case where this
* node may be orphaned.
*/
@property(nonatomic, readonly) fml::WeakPtr<flutter::AccessibilityBridge> bridge;
/**
* Due to the fact that VoiceOver may hold onto SemanticObjects even after it shuts down,
* there can be situations where the AccessibilityBridge is shutdown, but the SemanticObject
* will still be alive. If VoiceOver is turned on again, it may try to access this orphaned
* SemanticObject. Methods that are called from the accessiblity framework should use
* this to guard against this case by just returning early if its bridge has been shutdown.
*
* See https://github.com/flutter/flutter/issues/43795 for more information.
*/
- (BOOL)isAccessibilityBridgeAlive;
/**
* The semantics node used to produce this semantics object.
*/
......
......@@ -140,6 +140,10 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
#pragma mark - Semantic object methods
- (BOOL)isAccessibilityBridgeAlive {
return [self bridge].get() != nil;
}
- (void)setSemanticsNode:(const flutter::SemanticsNode*)node {
_node = *node;
}
......@@ -169,6 +173,9 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
#pragma mark - UIAccessibility overrides
- (BOOL)isAccessibilityElement {
if (![self isAccessibilityBridgeAlive])
return false;
// Note: hit detection will only apply to elements that report
// -isAccessibilityElement of YES. The framework will continue scanning the
// entire element tree looking for such a hit.
......@@ -238,24 +245,35 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
}
- (NSString*)accessibilityLabel {
if (![self isAccessibilityBridgeAlive])
return nil;
if ([self node].label.empty())
return nil;
return @([self node].label.data());
}
- (NSString*)accessibilityHint {
if (![self isAccessibilityBridgeAlive])
return nil;
if ([self node].hint.empty())
return nil;
return @([self node].hint.data());
}
- (NSString*)accessibilityValue {
if (![self isAccessibilityBridgeAlive])
return nil;
if ([self node].value.empty())
return nil;
return @([self node].value.data());
}
- (CGRect)accessibilityFrame {
if (![self isAccessibilityBridgeAlive])
return CGRectMake(0, 0, 0, 0);
if ([self node].HasFlag(flutter::SemanticsFlags::kIsHidden)) {
return [super accessibilityFrame];
}
......@@ -308,6 +326,8 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
#pragma mark - UIAccessibilityAction overrides
- (BOOL)accessibilityActivate {
if (![self isAccessibilityBridgeAlive])
return NO;
if (![self node].HasAction(flutter::SemanticsAction::kTap))
return NO;
[self bridge] -> DispatchSemanticsAction([self uid], flutter::SemanticsAction::kTap);
......@@ -315,6 +335,8 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
}
- (void)accessibilityIncrement {
if (![self isAccessibilityBridgeAlive])
return;
if ([self node].HasAction(flutter::SemanticsAction::kIncrease)) {
[self node].value = [self node].increasedValue;
[self bridge] -> DispatchSemanticsAction([self uid], flutter::SemanticsAction::kIncrease);
......@@ -322,6 +344,8 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
}
- (void)accessibilityDecrement {
if (![self isAccessibilityBridgeAlive])
return;
if ([self node].HasAction(flutter::SemanticsAction::kDecrease)) {
[self node].value = [self node].decreasedValue;
[self bridge] -> DispatchSemanticsAction([self uid], flutter::SemanticsAction::kDecrease);
......@@ -329,6 +353,8 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
}
- (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction {
if (![self isAccessibilityBridgeAlive])
return NO;
flutter::SemanticsAction action = GetSemanticsActionForScrollDirection(direction);
if (![self node].HasAction(action))
return NO;
......@@ -337,6 +363,8 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
}
- (BOOL)accessibilityPerformEscape {
if (![self isAccessibilityBridgeAlive])
return NO;
if (![self node].HasAction(flutter::SemanticsAction::kDismiss))
return NO;
[self bridge] -> DispatchSemanticsAction([self uid], flutter::SemanticsAction::kDismiss);
......@@ -346,6 +374,8 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
#pragma mark UIAccessibilityFocus overrides
- (void)accessibilityElementDidBecomeFocused {
if (![self isAccessibilityBridgeAlive])
return;
if ([self node].HasFlag(flutter::SemanticsFlags::kIsHidden)) {
[self bridge] -> DispatchSemanticsAction([self uid], flutter::SemanticsAction::kShowOnScreen);
}
......@@ -356,6 +386,8 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
}
- (void)accessibilityElementDidLoseFocus {
if (![self isAccessibilityBridgeAlive])
return;
if ([self node].HasAction(flutter::SemanticsAction::kDidLoseAccessibilityFocus)) {
[self bridge] -> DispatchSemanticsAction([self uid],
flutter::SemanticsAction::kDidLoseAccessibilityFocus);
......
......@@ -219,24 +219,35 @@
}
- (void)accessibilityElementDidBecomeFocused {
if (![self isAccessibilityBridgeAlive])
return;
[[self textInputSurrogate] accessibilityElementDidBecomeFocused];
[super accessibilityElementDidBecomeFocused];
}
- (void)accessibilityElementDidLoseFocus {
if (![self isAccessibilityBridgeAlive])
return;
[[self textInputSurrogate] accessibilityElementDidLoseFocus];
[super accessibilityElementDidLoseFocus];
}
- (BOOL)accessibilityElementIsFocused {
if (![self isAccessibilityBridgeAlive])
return false;
return [self node].HasFlag(flutter::SemanticsFlags::kIsFocused);
}
- (BOOL)accessibilityActivate {
if (![self isAccessibilityBridgeAlive])
return false;
return [[self textInputSurrogate] accessibilityActivate];
}
- (NSString*)accessibilityLabel {
if (![self isAccessibilityBridgeAlive])
return nil;
NSString* label = [super accessibilityLabel];
if (label != nil)
return label;
......@@ -244,6 +255,8 @@
}
- (NSString*)accessibilityHint {
if (![self isAccessibilityBridgeAlive])
return nil;
NSString* hint = [super accessibilityHint];
if (hint != nil)
return hint;
......@@ -251,6 +264,8 @@
}
- (NSString*)accessibilityValue {
if (![self isAccessibilityBridgeAlive])
return nil;
NSString* value = [super accessibilityValue];
if (value != nil)
return value;
......@@ -258,6 +273,8 @@
}
- (UIAccessibilityTraits)accessibilityTraits {
if (![self isAccessibilityBridgeAlive])
return 0;
// Adding UIAccessibilityTraitKeyboardKey to the trait list so that iOS treats it like
// a keyboard entry control, thus adding support for text editing features, such as
// pinch to select text, and up/down fling to move cursor.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册