From 8cb25d3de494c6d9357a1c199e1a9dbff9be9948 Mon Sep 17 00:00:00 2001 From: Artem Semenov Date: Fri, 13 Jan 2023 19:39:56 +0000 Subject: [PATCH] 8298644: JNI call of getCurrentComponent on a wrong thread Reviewed-by: avu, serb, kizune --- .../sun/lwawt/macosx/CAccessibility.java | 14 ++++++++- .../awt/a11y/OutlineRowAccessibility.m | 24 ++++----------- .../share/classes/javax/swing/JTree.java | 21 +++++++++++++ .../classes/sun/swing/SwingAccessor.java | 30 +++++++++++++++++-- 4 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index c2746dad0a8..67c8f184ecc 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -42,7 +42,6 @@ import java.util.HashSet; import java.util.Set; import java.util.concurrent.Callable; import java.util.Arrays; -import java.util.function.Function; import javax.accessibility.Accessible; import javax.accessibility.AccessibleAction; @@ -67,6 +66,7 @@ import javax.swing.KeyStroke; import sun.awt.AWTAccessor; import sun.lwawt.LWWindowPeer; +import sun.swing.SwingAccessor; class CAccessibility implements PropertyChangeListener { private static Set ignoredRoles; @@ -824,6 +824,18 @@ class CAccessibility implements PropertyChangeListener { }, c); } + // This method is called from the native in OutlineRowAccessibility.m + private static Accessible getAccessibleCurrentAccessible(Accessible a, Component c) { + if (a == null) return null; + return invokeAndWait(() -> { + AccessibleContext ac = a.getAccessibleContext(); + if (ac != null) { + return SwingAccessor.getAccessibleComponentAccessor().getCurrentAccessible(ac); + } + return null; + }, c); + } + // This method is called from the native in ComboBoxAccessibility.m private static Accessible getAccessibleComboboxValue(Accessible a, Component c) { if (a == null) return null; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m index e80d60b958b..e1392785904 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m @@ -32,9 +32,7 @@ #import "OutlineAccessibility.h" #import "sun_lwawt_macosx_CAccessibility.h" -static jclass sjc_CAccessible = NULL; -#define GET_CACCESSIBLE_CLASS_RETURN(ret) \ - GET_CLASS_RETURN(sjc_CAccessible, "sun/lwawt/macosx/CAccessible", ret); +static jclass sjc_CAccessibility = NULL; @implementation OutlineRowAccessibility @@ -42,23 +40,11 @@ static jclass sjc_CAccessible = NULL; - (jobject)currentAccessibleWithENV:(JNIEnv *)env { - jobject jAxContext = getAxContext(env, fAccessible, fComponent); - if (jAxContext == NULL) return NULL; - jclass axContextClass = (*env)->GetObjectClass(env, jAxContext); - DECLARE_METHOD_RETURN(jm_getCurrentComponent, axContextClass, "getCurrentComponent", "()Ljava/awt/Component;", NULL); - jobject newComponent = (*env)->CallObjectMethod(env, jAxContext, jm_getCurrentComponent); + GET_CACCESSIBILITY_CLASS_RETURN(NULL); + DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleCurrentAccessible, sjc_CAccessibility, "getAccessibleCurrentAccessible", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/Accessible;", NULL); + jobject currentAccessible = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleCurrentAccessible, fAccessible, fComponent); CHECK_EXCEPTION(); - (*env)->DeleteLocalRef(env, jAxContext); - if (newComponent != NULL) { - GET_CACCESSIBLE_CLASS_RETURN(NULL); - DECLARE_STATIC_METHOD_RETURN(sjm_getCAccessible, sjc_CAccessible, "getCAccessible", "(Ljavax/accessibility/Accessible;)Lsun/lwawt/macosx/CAccessible;", NULL); - jobject currentAccessible = (*env)->CallStaticObjectMethod(env, sjc_CAccessible, sjm_getCAccessible, newComponent); - CHECK_EXCEPTION(); - (*env)->DeleteLocalRef(env, newComponent); - return currentAccessible; - } else { - return NULL; - } + return currentAccessible; } // NSAccessibilityElement protocol methods diff --git a/src/java.desktop/share/classes/javax/swing/JTree.java b/src/java.desktop/share/classes/javax/swing/JTree.java index a813bd95d07..7cecd30d66d 100644 --- a/src/java.desktop/share/classes/javax/swing/JTree.java +++ b/src/java.desktop/share/classes/javax/swing/JTree.java @@ -92,6 +92,7 @@ import javax.swing.tree.TreeSelectionModel; import sun.awt.AWTAccessor; import sun.awt.AWTAccessor.MouseEventAccessor; +import sun.swing.SwingAccessor; import sun.swing.SwingUtilities2; import sun.swing.SwingUtilities2.Section; @@ -4740,6 +4741,26 @@ public class JTree extends JComponent implements Scrollable, Accessible implements Accessible, AccessibleComponent, AccessibleSelection, AccessibleAction { + static { + SwingAccessor.setAccessibleComponentAccessor(new AccessibleJTreeNodeAccessor()); + } + + private static class AccessibleJTreeNodeAccessor implements SwingAccessor.AccessibleComponentAccessor { + + private AccessibleJTreeNodeAccessor() {} + + @Override + public Accessible getCurrentAccessible(AccessibleContext ac) { + if (ac instanceof AccessibleJTreeNode) { + Component c = ((AccessibleJTreeNode) ac).getCurrentComponent(); + if (c instanceof Accessible) { + return (Accessible)c; + } + } + return null; + } + } + private JTree tree = null; private TreeModel treeModel = null; private Object obj = null; diff --git a/src/java.desktop/share/classes/sun/swing/SwingAccessor.java b/src/java.desktop/share/classes/sun/swing/SwingAccessor.java index 05c741de4b1..0b823582e23 100644 --- a/src/java.desktop/share/classes/sun/swing/SwingAccessor.java +++ b/src/java.desktop/share/classes/sun/swing/SwingAccessor.java @@ -25,10 +25,13 @@ package sun.swing; -import java.awt.*; +import java.awt.Component; +import java.awt.Point; import java.lang.invoke.MethodHandles; -import javax.swing.*; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.swing.*; import javax.swing.text.JTextComponent; /** @@ -47,6 +50,14 @@ public final class SwingAccessor { private SwingAccessor() { } + /** + * This interface provides access to the renderer's accessibility component. + * For example, the renderer of a list element, a table cell, or a tree node + */ + public interface AccessibleComponentAccessor { + Accessible getCurrentAccessible(AccessibleContext ac); + } + /** * An accessor for the JComponent class. */ @@ -290,6 +301,21 @@ public final class SwingAccessor { SwingAccessor.keyStrokeAccessor = accessor; } + private static AccessibleComponentAccessor accessibleComponentAccessor = null; + + public static AccessibleComponentAccessor getAccessibleComponentAccessor() { + var access = accessibleComponentAccessor; + if (access == null) { + ensureClassInitialized(JTree.class); + access = accessibleComponentAccessor; + } + return access; + } + + public static void setAccessibleComponentAccessor(final AccessibleComponentAccessor accessibleAccessor) { + accessibleComponentAccessor = accessibleAccessor; + } + private static void ensureClassInitialized(Class c) { try { MethodHandles.lookup().ensureInitialized(c);