--- a/jdk/src/share/classes/java/awt/Component.java Sat May 12 17:46:00 2012 +0400
+++ b/jdk/src/share/classes/java/awt/Component.java Sat May 12 18:50:27 2012 +0400
@@ -7833,7 +7833,7 @@
if (focusLog.isLoggable(PlatformLogger.FINER)) {
focusLog.finer("clear global focus owner");
}
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwnerPriv();
}
if (focusLog.isLoggable(PlatformLogger.FINER)) {
focusLog.finer("returning result: " + res);
@@ -7914,7 +7914,7 @@
if (focusLog.isLoggable(PlatformLogger.FINER)) {
focusLog.finer("clear global focus owner");
}
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwnerPriv();
}
if (focusLog.isLoggable(PlatformLogger.FINER)) {
focusLog.finer("returning result: " + res);
@@ -7947,21 +7947,32 @@
if (rootAncestor != null) {
Container rootAncestorRootAncestor =
rootAncestor.getFocusCycleRootAncestor();
- KeyboardFocusManager.getCurrentKeyboardFocusManager().
- setGlobalCurrentFocusCycleRoot(
- (rootAncestorRootAncestor != null)
- ? rootAncestorRootAncestor
- : rootAncestor);
+
+ final Container fcr = (rootAncestorRootAncestor != null) ?
+ rootAncestorRootAncestor : rootAncestor;
+
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().
+ setGlobalCurrentFocusCycleRoot(fcr);
+ return null;
+ }
+ });
rootAncestor.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP);
} else {
- Window window = getContainingWindow();
+ final Window window = getContainingWindow();
if (window != null) {
Component toFocus = window.getFocusTraversalPolicy().
getDefaultComponent(window);
if (toFocus != null) {
- KeyboardFocusManager.getCurrentKeyboardFocusManager().
- setGlobalCurrentFocusCycleRoot(window);
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().
+ setGlobalCurrentFocusCycleRoot(window);
+ return null;
+ }
+ });
toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP);
}
}
--- a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java Sat May 12 17:46:00 2012 +0400
+++ b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java Sat May 12 18:50:27 2012 +0400
@@ -116,7 +116,7 @@
} else if (fe.getOppositeComponent() != null &&
doRestoreFocus(fe.getOppositeComponent(), vetoedComponent, false)) {
} else {
- clearGlobalFocusOwner();
+ clearGlobalFocusOwnerPriv();
}
}
private void restoreFocus(WindowEvent we) {
@@ -130,7 +130,7 @@
{
// do nothing, everything is done in restoreFocus()
} else {
- clearGlobalFocusOwner();
+ clearGlobalFocusOwnerPriv();
}
}
private boolean restoreFocus(Window aWindow, Component vetoedComponent,
@@ -141,7 +141,7 @@
if (toFocus != null && toFocus != vetoedComponent && doRestoreFocus(toFocus, vetoedComponent, false)) {
return true;
} else if (clearOnFailure) {
- clearGlobalFocusOwner();
+ clearGlobalFocusOwnerPriv();
return true;
} else {
return false;
@@ -164,7 +164,7 @@
{
return true;
} else if (clearOnFailure) {
- clearGlobalFocusOwner();
+ clearGlobalFocusOwnerPriv();
return true;
} else {
return false;
--- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java Sat May 12 17:46:00 2012 +0400
+++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java Sat May 12 18:50:27 2012 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -246,15 +246,7 @@
public static void setCurrentKeyboardFocusManager(
KeyboardFocusManager newManager) throws SecurityException
{
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- if (replaceKeyboardFocusManagerPermission == null) {
- replaceKeyboardFocusManagerPermission =
- new AWTPermission("replaceKeyboardFocusManager");
- }
- security.
- checkPermission(replaceKeyboardFocusManagerPermission);
- }
+ checkReplaceKFMPermission();
KeyboardFocusManager oldManager = null;
@@ -399,11 +391,6 @@
private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
/**
- * Error String for initializing SecurityExceptions.
- */
- private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
-
- /**
* We cache the permission used to verify that the calling thread is
* permitted to access the global focus state.
*/
@@ -503,17 +490,13 @@
* @see #setGlobalFocusOwner
* @throws SecurityException if this KeyboardFocusManager is not the
* current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
*/
protected Component getGlobalFocusOwner() throws SecurityException {
synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return focusOwner;
- } else {
- if (focusLog.isLoggable(PlatformLogger.FINER)) {
- focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- }
- throw new SecurityException(notPrivileged);
- }
+ checkKFMSecurity();
+ return focusOwner;
}
}
@@ -538,15 +521,23 @@
* @see Component#requestFocus()
* @see Component#requestFocusInWindow()
* @see Component#isFocusable
+ * @throws SecurityException if this KeyboardFocusManager is not the
+ * current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
* @beaninfo
* bound: true
*/
- protected void setGlobalFocusOwner(Component focusOwner) {
+ protected void setGlobalFocusOwner(Component focusOwner)
+ throws SecurityException
+ {
Component oldFocusOwner = null;
boolean shouldFire = false;
if (focusOwner == null || focusOwner.isFocusable()) {
synchronized (KeyboardFocusManager.class) {
+ checkKFMSecurity();
+
oldFocusOwner = getFocusOwner();
try {
@@ -584,6 +575,27 @@
}
/**
+ * Clears the focus owner at both the Java and native levels if the
+ * focus owner exists and resides in the same context as the calling thread,
+ * otherwise the method returns silently.
+ * <p>
+ * The focus owner component will receive a permanent FOCUS_LOST event.
+ * After this operation completes, the native windowing system will discard
+ * all user-generated KeyEvents until the user selects a new Component to
+ * receive focus, or a Component is given focus explicitly via a call to
+ * {@code requestFocus()}. This operation does not change the focused or
+ * active Windows.
+ *
+ * @see Component#requestFocus()
+ * @see java.awt.event.FocusEvent#FOCUS_LOST
+ */
+ public void clearFocusOwner() {
+ if (getFocusOwner() != null) {
+ clearGlobalFocusOwner();
+ }
+ }
+
+ /**
* Clears the global focus owner at both the Java and native levels. If
* there exists a focus owner, that Component will receive a permanent
* FOCUS_LOST event. After this operation completes, the native windowing
@@ -591,11 +603,26 @@
* a new Component to receive focus, or a Component is given focus
* explicitly via a call to <code>requestFocus()</code>. This operation
* does not change the focused or active Windows.
+ * <p>
+ * If a SecurityManager is installed, the calling thread must be granted
+ * the "replaceKeyboardFocusManager" AWTPermission. If this permission is
+ * not granted, this method will throw a SecurityException, and the current
+ * focus owner will not be cleared.
+ * <p>
+ * This method is intended to be used only by KeyboardFocusManager set as
+ * current KeyboardFocusManager for the calling thread's context. It is not
+ * for general client use.
*
+ * @see KeyboardFocusManager#clearFocusOwner
* @see Component#requestFocus()
* @see java.awt.event.FocusEvent#FOCUS_LOST
+ * @throws SecurityException if the calling thread does not have
+ * "replaceKeyboardFocusManager" permission
*/
- public void clearGlobalFocusOwner() {
+ public void clearGlobalFocusOwner()
+ throws SecurityException
+ {
+ checkReplaceKFMPermission();
if (!GraphicsEnvironment.isHeadless()) {
// Toolkit must be fully initialized, otherwise
// _clearGlobalFocusOwner will crash or throw an exception
@@ -609,6 +636,15 @@
peer.clearGlobalFocusOwner(activeWindow);
}
+ void clearGlobalFocusOwnerPriv() {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ clearGlobalFocusOwner();
+ return null;
+ }
+ });
+ }
+
Component getNativeFocusOwner() {
return peer.getCurrentFocusOwner();
}
@@ -660,29 +696,21 @@
* are equivalent unless a temporary focus change is currently in effect.
* In such a situation, the permanent focus owner will again be the focus
* owner when the temporary focus change ends.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
*
* @return the permanent focus owner
* @see #getPermanentFocusOwner
* @see #setGlobalPermanentFocusOwner
* @throws SecurityException if this KeyboardFocusManager is not the
* current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
*/
protected Component getGlobalPermanentFocusOwner()
throws SecurityException
{
synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return permanentFocusOwner;
- } else {
- if (focusLog.isLoggable(PlatformLogger.FINER)) {
- focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- }
- throw new SecurityException(notPrivileged);
- }
+ checkKFMSecurity();
+ return permanentFocusOwner;
}
}
@@ -708,16 +736,23 @@
* @see Component#requestFocus()
* @see Component#requestFocusInWindow()
* @see Component#isFocusable
+ * @throws SecurityException if this KeyboardFocusManager is not the
+ * current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
* @beaninfo
* bound: true
*/
protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner)
+ throws SecurityException
{
Component oldPermanentFocusOwner = null;
boolean shouldFire = false;
if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
synchronized (KeyboardFocusManager.class) {
+ checkKFMSecurity();
+
oldPermanentFocusOwner = getPermanentFocusOwner();
try {
@@ -770,27 +805,19 @@
* Returns the focused Window, even if the calling thread is in a different
* context than the focused Window. The focused Window is the Window that
* is or contains the focus owner.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
*
* @return the focused Window
* @see #getFocusedWindow
* @see #setGlobalFocusedWindow
* @throws SecurityException if this KeyboardFocusManager is not the
* current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
*/
protected Window getGlobalFocusedWindow() throws SecurityException {
synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return focusedWindow;
- } else {
- if (focusLog.isLoggable(PlatformLogger.FINER)) {
- focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- }
- throw new SecurityException(notPrivileged);
- }
+ checkKFMSecurity();
+ return focusedWindow;
}
}
@@ -812,15 +839,23 @@
* @see Component#requestFocus()
* @see Component#requestFocusInWindow()
* @see Window#isFocusableWindow
+ * @throws SecurityException if this KeyboardFocusManager is not the
+ * current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
* @beaninfo
* bound: true
*/
- protected void setGlobalFocusedWindow(Window focusedWindow) {
+ protected void setGlobalFocusedWindow(Window focusedWindow)
+ throws SecurityException
+ {
Window oldFocusedWindow = null;
boolean shouldFire = false;
if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
synchronized (KeyboardFocusManager.class) {
+ checkKFMSecurity();
+
oldFocusedWindow = getFocusedWindow();
try {
@@ -874,27 +909,19 @@
* or its children with special decorations, such as a highlighted title
* bar. The active Window is always either the focused Window, or the first
* Frame or Dialog that is an owner of the focused Window.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
*
* @return the active Window
* @see #getActiveWindow
* @see #setGlobalActiveWindow
* @throws SecurityException if this KeyboardFocusManager is not the
* current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
*/
protected Window getGlobalActiveWindow() throws SecurityException {
synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return activeWindow;
- } else {
- if (focusLog.isLoggable(PlatformLogger.FINER)) {
- focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- }
- throw new SecurityException(notPrivileged);
- }
+ checkKFMSecurity();
+ return activeWindow;
}
}
@@ -917,12 +944,20 @@
* @see #getGlobalActiveWindow
* @see Component#requestFocus()
* @see Component#requestFocusInWindow()
+ * @throws SecurityException if this KeyboardFocusManager is not the
+ * current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
* @beaninfo
* bound: true
*/
- protected void setGlobalActiveWindow(Window activeWindow) {
+ protected void setGlobalActiveWindow(Window activeWindow)
+ throws SecurityException
+ {
Window oldActiveWindow;
synchronized (KeyboardFocusManager.class) {
+ checkKFMSecurity();
+
oldActiveWindow = getActiveWindow();
if (focusLog.isLoggable(PlatformLogger.FINER)) {
focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
@@ -1194,10 +1229,6 @@
* Components represent the next and previous Components to focus during
* normal focus traversal. In that case, the current focus cycle root is
* used to differentiate among the possibilities.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
*
* @return the current focus cycle root, or null if the current focus cycle
* root is not a member of the calling thread's context
@@ -1205,19 +1236,15 @@
* @see #setGlobalCurrentFocusCycleRoot
* @throws SecurityException if this KeyboardFocusManager is not the
* current KeyboardFocusManager for the calling thread's context
+ * and if the calling thread does not have "replaceKeyboardFocusManager"
+ * permission
*/
protected Container getGlobalCurrentFocusCycleRoot()
throws SecurityException
{
synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return currentFocusCycleRoot;
- } else {
- if (focusLog.isLoggable(PlatformLogger.FINER)) {
- focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- }
- throw new SecurityException(notPrivileged);
- }
+ checkKFMSecurity();
+ return currentFocusCycleRoot;
}
}
@@ -1228,16 +1255,27 @@
* In that case, the current focus cycle root is used to differentiate
* among the possibilities.
* <p>
+ * If a SecurityManager is installed, the calling thread must be granted
+ * the "replaceKeyboardFocusManager" AWTPermission. If this permission is
+ * not granted, this method will throw a SecurityException, and the current
+ * focus cycle root will not be changed.
+ * <p>
* This method is intended to be used only by KeyboardFocusManagers and
* focus implementations. It is not for general client use.
*
* @param newFocusCycleRoot the new focus cycle root
* @see #getCurrentFocusCycleRoot
* @see #getGlobalCurrentFocusCycleRoot
+ * @throws SecurityException if the calling thread does not have
+ * "replaceKeyboardFocusManager" permission
* @beaninfo
* bound: true
*/
- public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
+ public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot)
+ throws SecurityException
+ {
+ checkReplaceKFMPermission();
+
Container oldFocusCycleRoot;
synchronized (KeyboardFocusManager.class) {
@@ -3058,4 +3096,39 @@
: null;
}
}
+
+ private static void checkReplaceKFMPermission()
+ throws SecurityException
+ {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ if (replaceKeyboardFocusManagerPermission == null) {
+ replaceKeyboardFocusManagerPermission =
+ new AWTPermission("replaceKeyboardFocusManager");
+ }
+ security.
+ checkPermission(replaceKeyboardFocusManagerPermission);
+ }
+ }
+
+ // Checks if this KeyboardFocusManager instance is the current KFM,
+ // or otherwise checks if the calling thread has "replaceKeyboardFocusManager"
+ // permission. Here's the reasoning to do so:
+ //
+ // A system KFM instance (which is the current KFM by default) may have no
+ // "replaceKFM" permission when a client code is on the call stack beneath,
+ // but still it should be able to execute the methods protected by this check
+ // due to the system KFM is trusted (and so it does like "privileged").
+ //
+ // If this KFM instance is not the current KFM but the client code has all
+ // permissions we can't throw SecurityException because it would contradict
+ // the security concepts. In this case the trusted client code is responsible
+ // for calling the secured methods from KFM instance which is not current.
+ private void checkKFMSecurity()
+ throws SecurityException
+ {
+ if (this != getCurrentKeyboardFocusManager()) {
+ checkReplaceKFMPermission();
+ }
+ }
}
--- a/jdk/src/share/classes/java/awt/Window.java Sat May 12 17:46:00 2012 +0400
+++ b/jdk/src/share/classes/java/awt/Window.java Sat May 12 18:50:27 2012 +0400
@@ -2568,7 +2568,7 @@
}
}
KeyboardFocusManager.getCurrentKeyboardFocusManager().
- clearGlobalFocusOwner();
+ clearGlobalFocusOwnerPriv();
}
}