changeset 5988:17192e819910

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/8-cpu-1304/dev/jfx/rt
author kcr
date Fri, 06 Sep 2013 16:21:48 -0700
parents b3346e91e555 1da97ec90d4b
children 4b224f556d88
files modules/graphics/src/main/java/com/sun/javafx/application/PlatformImpl.java modules/graphics/src/main/java/javafx/scene/Scene.java modules/graphics/src/main/java/javafx/scene/input/Dragboard.java
diffstat 13 files changed, 286 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/javafx/application/PlatformImpl.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/com/sun/javafx/application/PlatformImpl.java	Fri Sep 06 16:21:48 2013 -0700
@@ -46,6 +46,7 @@
 import com.sun.javafx.tk.TKStage;
 import com.sun.javafx.tk.Toolkit;
 import java.security.AccessController;
+import java.security.AllPermission;
 import java.security.PrivilegedAction;
 
 public class PlatformImpl {
@@ -456,77 +457,26 @@
     }
 
     public static boolean isSupported(ConditionalFeature feature) {
-        switch (feature) {
-            case GRAPHICS:
-                if (isGraphicsSupported == null) {
-                    isGraphicsSupported = checkForClass("javafx.stage.Stage");
+        final boolean supported = isSupportedImpl(feature);
+        if (supported && (feature == ConditionalFeature.TRANSPARENT_WINDOW)) {
+            // some features require the application to have the corresponding
+            // permissions, if the application doesn't have them, the platform
+            // will behave as if the feature wasn't supported
+            final SecurityManager securityManager =
+                    System.getSecurityManager();
+            if (securityManager != null) {
+                try {
+                    securityManager.checkPermission(new AllPermission());
+                } catch (final SecurityException e) {
+                    return false;
                 }
-                return isGraphicsSupported;
-            case CONTROLS:
-                if (isControlsSupported == null) {
-                    isControlsSupported = checkForClass(
-                            "javafx.scene.control.Control");
-                }
-                return isControlsSupported;
-            case MEDIA:
-                if (isMediaSupported == null) {
-                    isMediaSupported = checkForClass(
-                            "javafx.scene.media.MediaView");
-                }
-                return isMediaSupported;
-            case WEB:
-                if (isWebSupported == null) {
-                    isWebSupported = checkForClass("javafx.scene.web.WebView");
-                }
-                return isWebSupported;
-            case SWT:
-                if (isSWTSupported == null) {
-                    isSWTSupported = checkForClass("javafx.embed.swt.FXCanvas");
-                }
-                return isSWTSupported;
-            case SWING:
-                if (isSwingSupported == null) {
-                    isSwingSupported = 
-                        // check for JComponent first, it may not be present
-                        checkForClass("javax.swing.JComponent") &&
-                        checkForClass("javafx.embed.swing.JFXPanel");
-                }
-                return isSwingSupported;
-            case FXML:
-                if (isFXMLSupported == null) {
-                    isFXMLSupported = checkForClass("javafx.fxml.FXMLLoader")
-                            && checkForClass("javax.xml.stream.XMLInputFactory");
-                }
-                return isFXMLSupported;
-            case TWO_LEVEL_FOCUS:
-                if (hasTwoLevelFocus == null) {
-                    return Toolkit.getToolkit().isSupported(feature);
-                }
-                return hasTwoLevelFocus;
-            case VIRTUAL_KEYBOARD:
-                if (hasVirtualKeyboard == null) {
-                    return Toolkit.getToolkit().isSupported(feature);
-                }
-                return hasVirtualKeyboard;
-            case INPUT_TOUCH:
-                if (hasTouch == null) {
-                    return Toolkit.getToolkit().isSupported(feature);
-                }
-                return hasTouch;
-            case INPUT_MULTITOUCH:
-                if (hasMultiTouch == null) {
-                    return Toolkit.getToolkit().isSupported(feature);
-                }
-                return hasMultiTouch;
-            case INPUT_POINTER:
-                if (hasPointer == null) {
-                    return Toolkit.getToolkit().isSupported(feature);
-                }
-                return hasPointer;
-            default:
-                return Toolkit.getToolkit().isSupported(feature);
+            }
+
+            return true;
         }
-    }
+
+        return supported;
+   }
 
     public static interface FinishListener {
         public void idle(boolean implicitExit);
@@ -663,4 +613,77 @@
             StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheetUrl);
         }
     }
+
+    private static boolean isSupportedImpl(ConditionalFeature feature) {
+        switch (feature) {
+            case GRAPHICS:
+                if (isGraphicsSupported == null) {
+                    isGraphicsSupported = checkForClass("javafx.stage.Stage");
+                }
+                return isGraphicsSupported;
+            case CONTROLS:
+                if (isControlsSupported == null) {
+                    isControlsSupported = checkForClass(
+                            "javafx.scene.control.Control");
+                }
+                return isControlsSupported;
+            case MEDIA:
+                if (isMediaSupported == null) {
+                    isMediaSupported = checkForClass(
+                            "javafx.scene.media.MediaView");
+                }
+                return isMediaSupported;
+            case WEB:
+                if (isWebSupported == null) {
+                    isWebSupported = checkForClass("javafx.scene.web.WebView");
+                }
+                return isWebSupported;
+            case SWT:
+                if (isSWTSupported == null) {
+                    isSWTSupported = checkForClass("javafx.embed.swt.FXCanvas");
+                }
+                return isSWTSupported;
+            case SWING:
+                if (isSwingSupported == null) {
+                    isSwingSupported =
+                        // check for JComponent first, it may not be present
+                        checkForClass("javax.swing.JComponent") &&
+                        checkForClass("javafx.embed.swing.JFXPanel");
+                }
+                return isSwingSupported;
+            case FXML:
+                if (isFXMLSupported == null) {
+                    isFXMLSupported = checkForClass("javafx.fxml.FXMLLoader")
+                            && checkForClass("javax.xml.stream.XMLInputFactory");
+                }
+                return isFXMLSupported;
+            case TWO_LEVEL_FOCUS:
+                if (hasTwoLevelFocus == null) {
+                    return Toolkit.getToolkit().isSupported(feature);
+                }
+                return hasTwoLevelFocus;
+            case VIRTUAL_KEYBOARD:
+                if (hasVirtualKeyboard == null) {
+                    return Toolkit.getToolkit().isSupported(feature);
+                }
+                return hasVirtualKeyboard;
+            case INPUT_TOUCH:
+                if (hasTouch == null) {
+                    return Toolkit.getToolkit().isSupported(feature);
+                }
+                return hasTouch;
+            case INPUT_MULTITOUCH:
+                if (hasMultiTouch == null) {
+                    return Toolkit.getToolkit().isSupported(feature);
+                }
+                return hasMultiTouch;
+            case INPUT_POINTER:
+                if (hasPointer == null) {
+                    return Toolkit.getToolkit().isSupported(feature);
+                }
+                return hasPointer;
+            default:
+                return Toolkit.getToolkit().isSupported(feature);
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/scene/input/DragboardHelper.java	Fri Sep 06 16:21:48 2013 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.scene.input;
+
+import javafx.scene.input.Dragboard;
+
+/**
+ * Used to access internal methods of Dragboard.
+ */
+public class DragboardHelper {
+    private static DragboardAccessor dragboardAccessor;
+
+    static {
+        forceInit(Dragboard.class);
+    }
+
+    private DragboardHelper() {
+    }
+
+    public static void setDataAccessRestriction(Dragboard dragboard,
+            boolean restricted) {
+        dragboardAccessor.setDataAccessRestriction(dragboard, restricted);
+    }
+
+    public static void setDragboardAccessor(final DragboardAccessor newAccessor) {
+        if (dragboardAccessor != null) {
+            throw new IllegalStateException();
+        }
+
+        dragboardAccessor = newAccessor;
+    }
+
+    public interface DragboardAccessor {
+        void setDataAccessRestriction(Dragboard dragboard, boolean restricted);
+    }
+
+    private static void forceInit(final Class<?> classToInit) {
+        try {
+            Class.forName(classToInit.getName(), true,
+                          classToInit.getClassLoader());
+        } catch (final ClassNotFoundException e) {
+            throw new AssertionError(e);  // Can't happen
+        }
+    }
+}
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java	Fri Sep 06 16:21:48 2013 -0700
@@ -97,7 +97,7 @@
     }
 
     @Override
-    public TKStage createTKPopupStage(Window peerWindow, TKStage owner, AccessControlContext acc) {
+    public TKStage createTKPopupStage(Window peerWindow, StageStyle popupStyle, TKStage owner, AccessControlContext acc) {
         throw new UnsupportedOperationException("Not supported yet.");
     }
 
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/Toolkit.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/Toolkit.java	Fri Sep 06 16:21:48 2013 -0700
@@ -276,7 +276,7 @@
     public abstract TKStage createTKStage(Window peerWindow, StageStyle stageStyle, boolean primary,
             Modality modality, TKStage owner, boolean rtl, AccessControlContext acc);
 
-    public abstract TKStage createTKPopupStage(Window peerWindow, TKStage owner, AccessControlContext acc);
+    public abstract TKStage createTKPopupStage(Window peerWindow, StageStyle popupStyle, TKStage owner, AccessControlContext acc);
     public abstract TKStage createTKEmbeddedStage(HostInterface host, AccessControlContext acc);
 
     /**
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java	Fri Sep 06 16:21:48 2013 -0700
@@ -568,10 +568,11 @@
     }
 
     @Override public TKStage createTKPopupStage(Window peerWindow,
+                                                StageStyle popupStyle,
                                                 TKStage owner,
                                                 AccessControlContext acc) {
         assertToolkitRunning();
-        WindowStage stage = new WindowStage(peerWindow, StageStyle.TRANSPARENT, null, owner);
+        WindowStage stage = new WindowStage(peerWindow, popupStyle, null, owner);
         stage.setSecurityContext(acc);
         stage.setIsPopup();
         stage.init(systemMenu);
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java	Fri Sep 06 16:21:48 2013 -0700
@@ -154,7 +154,10 @@
                 boolean focusable = true;
                 int windowMask = rtl ? Window.RIGHT_TO_LEFT : 0;
                 if (isPopupStage) { // TODO: make it a stage style?
-                    windowMask |= Window.TRANSPARENT | Window.POPUP;
+                    windowMask |= Window.POPUP;
+                    if (style == StageStyle.TRANSPARENT) {
+                        windowMask |= Window.TRANSPARENT;
+                    }
                     focusable = false;
                 } else {
                     switch (style) {
--- a/modules/graphics/src/main/java/javafx/application/ConditionalFeature.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/javafx/application/ConditionalFeature.java	Fri Sep 06 16:21:48 2013 -0700
@@ -132,6 +132,16 @@
      * NOTE: Currently, this support is available on all platforms
      * except Linux systems without the XComposite extension. The
      * XShape extension is used in that case, so the window edges are aliased.
+     * </p>
+     * <p>
+     * NOTE: In an environment with enabled security manager (for example in
+     * applet mode), usage of transparent windows is protected by security
+     * checks. If the application doesn't have the required permissions, it
+     * won't be able to use this feature and the system will appear as if the
+     * support for transparent windows wasn't implemented. This includes
+     * returning false from the Platform.isSupported(TRANSPARENT_WINDOW) test.
+     * </p>
+     *
      * @since JavaFX 2.2
      */
     TRANSPARENT_WINDOW,
--- a/modules/graphics/src/main/java/javafx/scene/Scene.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/javafx/scene/Scene.java	Fri Sep 06 16:21:48 2013 -0700
@@ -121,6 +121,7 @@
 import com.sun.javafx.scene.CssFlags;
 import com.sun.javafx.scene.SceneEventDispatcher;
 import com.sun.javafx.scene.SceneHelper;
+import com.sun.javafx.scene.input.DragboardHelper;
 import com.sun.javafx.scene.input.InputEventUtils;
 import com.sun.javafx.scene.input.KeyCodeMap;
 import com.sun.javafx.scene.input.PickResultChooser;
@@ -2755,7 +2756,17 @@
                 DragEvent dragEvent =
                         new DragEvent(DragEvent.ANY, dndGesture.dragboard, x, y, screenX, screenY,
                                 transferMode, null, null, pick(x, y));
-                TransferMode tm = dndGesture.processTargetDrop(dragEvent);
+                // Data dropped to the app can be accessed without restriction
+                DragboardHelper.setDataAccessRestriction(dndGesture.dragboard, false);
+
+                TransferMode tm;
+                try {
+                    tm = dndGesture.processTargetDrop(dragEvent);
+                } finally {
+                    DragboardHelper.setDataAccessRestriction(
+                            dndGesture.dragboard, true);
+                }
+                
                 if (dndGesture.source == null) {
                     dndGesture.dragboard = null;
                     dndGesture = null;
@@ -2888,7 +2899,15 @@
                                 mouseEvent.getSource(), target,
                                 MouseEvent.DRAG_DETECTED);
 
-                        fireEvent(target, detectedEvent);
+                        try {
+                            fireEvent(target, detectedEvent);
+                        } finally {
+                            // Putting data to dragboard finished, restrict access to them
+                            if (dragboard != null) {
+                                DragboardHelper.setDataAccessRestriction(
+                                        dragboard, true);
+                            }
+                        }
                     }
 
                     dragDetectedProcessed();
@@ -2916,7 +2935,15 @@
             processingDragDetected();
 
             final EventTarget target = de.getPickResult().getIntersectedNode();
-            fireEvent(target != null ? target : Scene.this, me);
+            try {
+                fireEvent(target != null ? target : Scene.this, me);
+            } finally {
+                // Putting data to dragboard finished, restrict access to them
+                if (dragboard != null) {
+                    DragboardHelper.setDataAccessRestriction(
+                            dragboard, true);
+                }
+            }
 
             dragDetectedProcessed();
 
@@ -3117,6 +3144,10 @@
             } else if (dragboard == null) {
                 dragboard = createDragboard(null, true);
             }
+
+            // The app can see what it puts to dragboard without restriction
+            DragboardHelper.setDataAccessRestriction(dragboard, false);
+
             this.source = source;
             potentialTarget = source;
             sourceTransferModes = t;
@@ -3165,7 +3196,15 @@
                 DragEvent dragEvent =
                         new DragEvent(DragEvent.ANY, dndGesture.dragboard, x, y, screenX, screenY,
                         transferMode, null, null, null);
-                dndGesture.processDropEnd(dragEvent);
+
+                // DRAG_DONE event is delivered to gesture source, it can access
+                // its own data without restriction
+                DragboardHelper.setDataAccessRestriction(dndGesture.dragboard, false);
+                try {
+                    dndGesture.processDropEnd(dragEvent);
+                } finally {
+                    DragboardHelper.setDataAccessRestriction(dndGesture.dragboard, true);
+                }
                 dndGesture = null;
             }
         }
--- a/modules/graphics/src/main/java/javafx/scene/input/Clipboard.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/javafx/scene/input/Clipboard.java	Fri Sep 06 16:21:48 2013 -0700
@@ -248,6 +248,13 @@
      */
     public final Object getContent(DataFormat dataFormat) {
         Toolkit.getToolkit().checkFxUserThread();
+        return getContentImpl(dataFormat);
+    }
+
+    /**
+     * Getting content overridable by internal subclasses.
+     */
+    Object getContentImpl(DataFormat dataFormat) {
         return peer.getContent(dataFormat);
     }
 
--- a/modules/graphics/src/main/java/javafx/scene/input/Dragboard.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/javafx/scene/input/Dragboard.java	Fri Sep 06 16:21:48 2013 -0700
@@ -25,8 +25,10 @@
 
 package javafx.scene.input;
 
+import java.security.AllPermission;
 import java.util.Set;
 
+import com.sun.javafx.scene.input.DragboardHelper;
 import com.sun.javafx.tk.TKClipboard;
 import com.sun.javafx.tk.TKScene;
 import javafx.scene.image.Image;
@@ -37,10 +39,26 @@
  */
 public final class Dragboard extends Clipboard {
 
+    /**
+     * Whether access to the data requires a permission.
+     */
+    private boolean dataAccessRestricted = true;
+
     Dragboard(TKClipboard peer) {
         super(peer);
     }
 
+    @Override
+    Object getContentImpl(DataFormat dataFormat) {
+        if (dataAccessRestricted) {
+            final SecurityManager securityManager = System.getSecurityManager();
+            if (securityManager != null) {
+                securityManager.checkPermission(new AllPermission());
+            }
+        }
+        return super.getContentImpl(dataFormat);
+    }
+
     /**
      * Gets set of transport modes supported by source of this drag opeation.
      * @return set of supported transfer modes
@@ -156,4 +174,15 @@
     public double getDragViewOffsetY() {
         return peer.getDragViewOffsetY();
     }
+
+    static {
+        // This is used by classes in different packages to get access to
+        // private and package private methods.
+        DragboardHelper.setDragboardAccessor(new DragboardHelper.DragboardAccessor() {
+            @Override
+            public void setDataAccessRestriction(Dragboard dragboard, boolean restricted) {
+                dragboard.dataAccessRestricted = restricted;
+            }
+        });
+    }
 }
--- a/modules/graphics/src/main/java/javafx/stage/PopupWindow.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/javafx/stage/PopupWindow.java	Fri Sep 06 16:21:48 2013 -0700
@@ -59,6 +59,7 @@
 import com.sun.javafx.stage.WindowCloseRequestHandler;
 import com.sun.javafx.stage.WindowEventDispatcher;
 import com.sun.javafx.tk.Toolkit;
+import java.security.AllPermission;
 import javafx.beans.property.ReadOnlyObjectProperty;
 import javafx.beans.property.ReadOnlyObjectWrapper;
 import javafx.event.EventTarget;
@@ -447,7 +448,18 @@
         Toolkit toolkit = Toolkit.getToolkit();
         if (visible && (impl_peer == null)) {
             // Setup the peer
-            impl_peer = toolkit.createTKPopupStage(this, getOwnerWindow().impl_getPeer(), acc);
+            StageStyle popupStyle;
+            try {
+                final SecurityManager securityManager =
+                        System.getSecurityManager();
+                if (securityManager != null) {
+                    securityManager.checkPermission(new AllPermission());
+                }
+                popupStyle = StageStyle.TRANSPARENT;
+            } catch (final SecurityException e) {
+                popupStyle = StageStyle.UNDECORATED;
+            }
+            impl_peer = toolkit.createTKPopupStage(this, popupStyle, getOwnerWindow().impl_getPeer(), acc);
             peerListener = new PopupWindowPeerListener(PopupWindow.this);
         }
     }
--- a/modules/graphics/src/main/java/javafx/stage/Stage.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/main/java/javafx/stage/Stage.java	Fri Sep 06 16:21:48 2013 -0700
@@ -50,6 +50,7 @@
 import com.sun.javafx.tk.TKPulseListener;
 import com.sun.javafx.tk.TKStage;
 import com.sun.javafx.tk.Toolkit;
+import java.security.AllPermission;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.DoublePropertyBase;
 import javafx.beans.property.ObjectProperty;
@@ -1043,7 +1044,20 @@
             Scene scene = getScene();
             boolean rtl = scene != null && scene.getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT;
 
-            impl_peer = toolkit.createTKStage(this, getStyle(), isPrimary(), getModality(), tkStage, rtl, acc);
+            StageStyle stageStyle = getStyle();
+            if (stageStyle == StageStyle.TRANSPARENT) {
+                final SecurityManager securityManager =
+                        System.getSecurityManager();
+                if (securityManager != null) {
+                    try {
+                        securityManager.checkPermission(new AllPermission());
+                    } catch (final SecurityException e) {
+                        stageStyle = StageStyle.UNDECORATED;
+                    }
+                }
+            }
+            impl_peer = toolkit.createTKStage(this, stageStyle, isPrimary(),
+                                              getModality(), tkStage, rtl, acc);
             impl_peer.setMinimumSize((int) Math.ceil(getMinWidth()),
                     (int) Math.ceil(getMinHeight()));
             impl_peer.setMaximumSize((int) Math.floor(getMaxWidth()),
--- a/modules/graphics/src/test/java/com/sun/javafx/pgstub/StubToolkit.java	Fri Sep 06 15:30:31 2013 -0700
+++ b/modules/graphics/src/test/java/com/sun/javafx/pgstub/StubToolkit.java	Fri Sep 06 16:21:48 2013 -0700
@@ -126,7 +126,7 @@
     }
 
     @Override
-    public TKStage createTKPopupStage(Window peerWindow, TKStage owner, AccessControlContext acc) {
+    public TKStage createTKPopupStage(Window peerWindow, StageStyle popupStyle, TKStage owner, AccessControlContext acc) {
         return new StubPopupStage();
     }