changeset 7736:3d879a4dab44

RT-38357: [Accessibility] All calls from a11y native must go thru Access Control before user code is executed
author Felipe Heidrich <felipe.heidrich@oracle.com>
date Wed, 20 Aug 2014 09:45:23 -0700
parents 798a93a61616
children a4ba2aff078e
files modules/graphics/src/main/java/com/sun/glass/ui/Accessible.java modules/graphics/src/main/java/com/sun/javafx/tk/TKScene.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassScene.java modules/graphics/src/main/java/javafx/scene/Node.java modules/graphics/src/main/java/javafx/scene/Scene.java modules/graphics/src/test/java/com/sun/javafx/pgstub/StubScene.java
diffstat 6 files changed, 88 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/glass/ui/Accessible.java	Wed Aug 20 15:53:46 2014 +0200
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/Accessible.java	Wed Aug 20 09:45:23 2014 -0700
@@ -27,6 +27,9 @@
 
 import static javafx.scene.AccessibleAttribute.PARENT;
 import static javafx.scene.AccessibleAttribute.ROLE;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import com.sun.javafx.scene.NodeHelper;
 import com.sun.javafx.scene.SceneHelper;
 import javafx.scene.AccessibleAction;
@@ -40,13 +43,15 @@
     private EventHandler eventHandler;
     private View view;
 
-    public static class EventHandler {
+    public static abstract class EventHandler {
         public Object getAttribute(AccessibleAttribute attribute, Object... parameters) {
             return null;
         }
 
         public void executeAction(AccessibleAction action, Object... parameters) {
         }
+
+        public abstract AccessControlContext getAccessControlContext();
     }
 
     public EventHandler getEventHandler() {
@@ -115,27 +120,60 @@
         return null;
     }
 
-    public Object getAttribute(AccessibleAttribute attribute, Object... parameters) {
-        Object result = eventHandler.getAttribute(attribute, parameters);
-        if (result != null) {
-            Class<?> clazz = attribute.getReturnType();
-            if (clazz != null) {
-                try {
-                    clazz.cast(result);
-                } catch (Exception e) {
-                    String msg = "The expected return type for the " + attribute +
-                                 " attribute is " + clazz.getSimpleName() +
-                                 " but found " + result.getClass().getSimpleName();
-                    System.err.println(msg);
-                    return null; //Fail no exception
+    final AccessControlContext getAccessControlContext() {
+        AccessControlContext acc = eventHandler.getAccessControlContext();
+        if (acc == null) {
+            throw new RuntimeException("Could not get AccessControlContext for " + this);
+        }
+        return acc;
+    }
+
+    private class GetAttribute implements PrivilegedAction<Object> {
+        AccessibleAttribute attribute;
+        Object[] parameters;
+        @Override public Object run() {
+            Object result = eventHandler.getAttribute(attribute, parameters);
+            if (result != null) {
+                Class<?> clazz = attribute.getReturnType();
+                if (clazz != null) {
+                    try {
+                        clazz.cast(result);
+                    } catch (Exception e) {
+                        String msg = "The expected return type for the " + attribute +
+                                     " attribute is " + clazz.getSimpleName() +
+                                     " but found " + result.getClass().getSimpleName();
+                        System.err.println(msg);
+                        return null; //Fail no exception
+                    }
                 }
             }
+            return result;
         }
-        return result;
     }
 
+    private GetAttribute getAttribute = new GetAttribute();
+
+    public Object getAttribute(AccessibleAttribute attribute, Object... parameters) {
+        getAttribute.attribute = attribute;
+        getAttribute.parameters = parameters;
+        return AccessController.doPrivileged(getAttribute, getAccessControlContext());
+    }
+
+    private class ExecuteAction implements PrivilegedAction<Void> {
+        AccessibleAction action;
+        Object[] parameters;
+        @Override public Void run() {
+            eventHandler.executeAction(action, parameters);
+            return null;
+        }
+    }
+
+    private ExecuteAction executeAction = new ExecuteAction();
+
     public void executeAction(AccessibleAction action, Object... parameters) {
-        eventHandler.executeAction(action, parameters);
+        executeAction.action = action;
+        executeAction.parameters = parameters;
+        AccessController.doPrivileged(executeAction, getAccessControlContext());
     }
 
     public abstract void sendNotification(AccessibleAttribute notification);
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/TKScene.java	Wed Aug 20 15:53:46 2014 +0200
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/TKScene.java	Wed Aug 20 09:45:23 2014 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.javafx.tk;
 
+import java.security.AccessControlContext;
 import com.sun.javafx.sg.prism.NGCamera;
 import com.sun.javafx.sg.prism.NGLightBase;
 import com.sun.javafx.sg.prism.NGNode;
@@ -85,4 +86,6 @@
     public void entireSceneNeedsRepaint();
 
     public TKClipboard createDragboard(boolean isDragSource);
+
+    public AccessControlContext getAccessControlContext();
 }
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassScene.java	Wed Aug 20 15:53:46 2014 +0200
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassScene.java	Wed Aug 20 09:45:23 2014 -0700
@@ -94,7 +94,8 @@
     }
 
     // To be used by subclasses to enforce context check
-    final AccessControlContext getAccessControlContext() {
+    @Override
+    public final AccessControlContext getAccessControlContext() {
         if (accessCtrlCtx == null) {
             throw new RuntimeException("Scene security context has not been set!");
         }
--- a/modules/graphics/src/main/java/javafx/scene/Node.java	Wed Aug 20 15:53:46 2014 +0200
+++ b/modules/graphics/src/main/java/javafx/scene/Node.java	Wed Aug 20 09:45:23 2014 -0700
@@ -100,6 +100,7 @@
 import javafx.scene.transform.Transform;
 import javafx.stage.Window;
 import javafx.util.Callback;
+import java.security.AccessControlContext;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -9429,6 +9430,23 @@
         if (accessible == null) {
             accessible = Application.GetApplication().createAccessible();
             accessible.setEventHandler(new Accessible.EventHandler() {
+                @SuppressWarnings("deprecation")
+                @Override public AccessControlContext getAccessControlContext() {
+                    Scene scene = getScene();
+                    if (scene == null) throw new RuntimeException("Accessbility requested for node not on a scene");
+                    if (scene.impl_getPeer() != null) {
+                        return scene.impl_getPeer().getAccessControlContext();
+                    } else {
+                        /* In some rare cases the accessible for a Node is needed
+                         * before its scene is made visible. For example, the screen reader
+                         * might ask a Menu for its ContextMenu before the ContextMenu
+                         * is made visible. That is a problem because the Window for the
+                         * ContextMenu is only created immediately before the first time
+                         * it is shown.
+                         */
+                        return scene.acc;
+                    }
+                }
                 @Override public Object getAttribute(AccessibleAttribute attribute, Object... parameters) {
                     return queryAccessibleAttribute(attribute, parameters);
                 }
--- a/modules/graphics/src/main/java/javafx/scene/Scene.java	Wed Aug 20 15:53:46 2014 +0200
+++ b/modules/graphics/src/main/java/javafx/scene/Scene.java	Wed Aug 20 09:45:23 2014 -0700
@@ -152,7 +152,7 @@
 
     private int dirtyBits;
 
-    private final AccessControlContext acc = AccessController.getContext();
+    final AccessControlContext acc = AccessController.getContext();
 
     private Camera defaultCamera;
 
@@ -6275,6 +6275,10 @@
         if (accessible == null) {
             accessible = Application.GetApplication().createAccessible();
             accessible.setEventHandler(new Accessible.EventHandler() {
+                @Override public AccessControlContext getAccessControlContext() {
+                    return impl_getPeer().getAccessControlContext();
+                }
+
                 @Override public Object getAttribute(AccessibleAttribute attribute,
                                                      Object... parameters) {
                     switch (attribute) {
--- a/modules/graphics/src/test/java/com/sun/javafx/pgstub/StubScene.java	Wed Aug 20 15:53:46 2014 +0200
+++ b/modules/graphics/src/test/java/com/sun/javafx/pgstub/StubScene.java	Wed Aug 20 09:45:23 2014 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.javafx.pgstub;
 
+import java.security.AccessControlContext;
 import com.sun.javafx.sg.prism.NGCamera;
 import com.sun.javafx.sg.prism.NGLightBase;
 import com.sun.javafx.sg.prism.NGNode;
@@ -133,4 +134,9 @@
     public NGCamera getCamera() {
         return camera;
     }
+
+    @Override
+    public AccessControlContext getAccessControlContext() {
+        return null;
+    }
 }