1 /*
2 * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
106 * }</pre><p>
107 *
108 * Since a separate AppContext can exist for each ThreadGroup, trusted
109 * and untrusted code have access to different Foo instances. This allows
110 * untrusted code access to "system-wide" services -- the service remains
111 * within the AppContext "sandbox". For example, say a malicious applet
112 * wants to peek all of the key events on the EventQueue to listen for
113 * passwords; if separate EventQueues are used for each ThreadGroup
114 * using AppContexts, the only key events that applet will be able to
115 * listen to are its own. A more reasonable applet request would be to
116 * change the Swing default look-and-feel; with that default stored in
117 * an AppContext, the applet's look-and-feel will change without
118 * disrupting other applets or potentially the browser itself.<p>
119 *
120 * Because the AppContext is a facility for safely extending application
121 * service support to applets, none of its methods may be blocked by a
122 * a SecurityManager check in a valid Java implementation. Applets may
123 * therefore safely invoke any of its methods without worry of being
124 * blocked.
125 *
126 * Note: If a SecurityManager is installed which derives from
127 * sun.awt.AWTSecurityManager, it may override the
128 * AWTSecurityManager.getAppContext() method to return the proper
129 * AppContext based on the execution context, in the case where
130 * the default ThreadGroup-based AppContext indexing would return
131 * the main "system" AppContext. For example, in an applet situation,
132 * if a system thread calls into an applet, rather than returning the
133 * main "system" AppContext (the one corresponding to the system thread),
134 * an installed AWTSecurityManager may return the applet's AppContext
135 * based on the execution context.
136 *
137 * @author Thomas Ball
138 * @author Fred Ecks
139 */
140 public final class AppContext {
141 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.AppContext");
142
143 /* Since the contents of an AppContext are unique to each Java
144 * session, this class should never be serialized. */
145
146 /*
147 * The key to put()/get() the Java EventQueue into/from the AppContext.
148 */
149 public static final Object EVENT_QUEUE_KEY = new StringBuffer("EventQueue");
150
151 /*
152 * The keys to store EventQueue push/pop lock and condition.
153 */
154 public static final Object EVENT_QUEUE_LOCK_KEY = new StringBuilder("EventQueue.Lock");
155 public static final Object EVENT_QUEUE_COND_KEY = new StringBuilder("EventQueue.Condition");
156
270 // code is unaffected by the move to multiple AppContext ability.
271 AccessController.doPrivileged(new PrivilegedAction<Void>() {
272 public Void run() {
273 ThreadGroup currentThreadGroup =
274 Thread.currentThread().getThreadGroup();
275 ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
276 while (parentThreadGroup != null) {
277 // Find the root ThreadGroup to construct our main AppContext
278 currentThreadGroup = parentThreadGroup;
279 parentThreadGroup = currentThreadGroup.getParent();
280 }
281
282 mainAppContext = SunToolkit.createNewAppContext(currentThreadGroup);
283 return null;
284 }
285 });
286 }
287
288 /**
289 * Returns the appropriate AppContext for the caller,
290 * as determined by its ThreadGroup. If the main "system" AppContext
291 * would be returned and there's an AWTSecurityManager installed, it
292 * is called to get the proper AppContext based on the execution
293 * context.
294 *
295 * @return the AppContext for the caller.
296 * @see java.lang.ThreadGroup
297 * @since 1.2
298 */
299 public static AppContext getAppContext() {
300 // we are standalone app, return the main app context
301 if (numAppContexts.get() == 1 && mainAppContext != null) {
302 return mainAppContext;
303 }
304
305 AppContext appContext = threadAppContext.get();
306
307 if (null == appContext) {
308 appContext = AccessController.doPrivileged(new PrivilegedAction<AppContext>()
309 {
310 public AppContext run() {
311 // Get the current ThreadGroup, and look for it and its
312 // parents in the hash from ThreadGroup to AppContext --
313 // it should be found, because we use createNewContext()
367
368 return context;
369 }
370 });
371 }
372
373 return appContext;
374 }
375
376 /**
377 * Returns true if the specified AppContext is the main AppContext.
378 *
379 * @param ctx the context to compare with the main context
380 * @return true if the specified AppContext is the main AppContext.
381 * @since 1.8
382 */
383 public static boolean isMainContext(AppContext ctx) {
384 return (ctx != null && ctx == mainAppContext);
385 }
386
387 private static AppContext getExecutionAppContext() {
388 SecurityManager securityManager = System.getSecurityManager();
389 if ((securityManager != null) &&
390 (securityManager instanceof AWTSecurityManager))
391 {
392 AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager;
393 AppContext secAppContext = awtSecMgr.getAppContext();
394 return secAppContext; // Return what we're told
395 }
396 return null;
397 }
398
399 private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout
400 // for disposal of all Frames
401 // (we wait for this time twice,
402 // once for dispose(), and once
403 // to clear the EventQueue).
404
405 private long THREAD_INTERRUPT_TIMEOUT = 1000;
406 // Default to 1-second timeout for all
407 // interrupted Threads to exit, and another
408 // 1 second for all stopped Threads to die.
409
410 /**
411 * Disposes of this AppContext, all of its top-level Frames, and
412 * all Threads and ThreadGroups contained within it.
413 *
414 * This method must be called from a Thread which is not contained
415 * within this AppContext.
416 *
417 * @exception IllegalThreadStateException if the current thread is
418 * contained within this AppContext
855 });
856 }
857
858 /**
859 * Returns the AppContext used for applet logging isolation, or null if
860 * the default global context can be used.
861 * If there's no applet, or if the caller is a stand alone application,
862 * or running in the main app context, returns null.
863 * Otherwise, returns the AppContext of the calling applet.
864 * @return null if the global default context can be used,
865 * an AppContext otherwise.
866 **/
867 public Object getAppletContext() {
868 // There's no AppContext: return null.
869 // No need to call getAppContext() if numAppContext == 0:
870 // it means that no AppContext has been created yet, and
871 // we don't want to trigger the creation of a main app
872 // context since we don't need it.
873 if (numAppContexts.get() == 0) return null;
874
875 // Get the context from the security manager
876 AppContext ecx = getExecutionAppContext();
877
878 // Not sure we really need to re-check numAppContexts here.
879 // If all applets have gone away then we could have a
880 // numAppContexts coming back to 0. So we recheck
881 // it here because we don't want to trigger the
882 // creation of a main AppContext in that case.
883 // This is probably not 100% MT-safe but should reduce
884 // the window of opportunity in which that issue could
885 // happen.
886 if (numAppContexts.get() > 0) {
887 // Defaults to thread group caching.
888 // This is probably not required as we only really need
889 // isolation in a deployed applet environment, in which
890 // case ecx will not be null when we reach here
891 // However it helps emulate the deployed environment,
892 // in tests for instance.
893 ecx = ecx != null ? ecx : getAppContext();
894 }
895
896 // getAppletContext() may be called when initializing the main
|
1 /*
2 * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
106 * }</pre><p>
107 *
108 * Since a separate AppContext can exist for each ThreadGroup, trusted
109 * and untrusted code have access to different Foo instances. This allows
110 * untrusted code access to "system-wide" services -- the service remains
111 * within the AppContext "sandbox". For example, say a malicious applet
112 * wants to peek all of the key events on the EventQueue to listen for
113 * passwords; if separate EventQueues are used for each ThreadGroup
114 * using AppContexts, the only key events that applet will be able to
115 * listen to are its own. A more reasonable applet request would be to
116 * change the Swing default look-and-feel; with that default stored in
117 * an AppContext, the applet's look-and-feel will change without
118 * disrupting other applets or potentially the browser itself.<p>
119 *
120 * Because the AppContext is a facility for safely extending application
121 * service support to applets, none of its methods may be blocked by a
122 * a SecurityManager check in a valid Java implementation. Applets may
123 * therefore safely invoke any of its methods without worry of being
124 * blocked.
125 *
126 * @author Thomas Ball
127 * @author Fred Ecks
128 */
129 public final class AppContext {
130 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.AppContext");
131
132 /* Since the contents of an AppContext are unique to each Java
133 * session, this class should never be serialized. */
134
135 /*
136 * The key to put()/get() the Java EventQueue into/from the AppContext.
137 */
138 public static final Object EVENT_QUEUE_KEY = new StringBuffer("EventQueue");
139
140 /*
141 * The keys to store EventQueue push/pop lock and condition.
142 */
143 public static final Object EVENT_QUEUE_LOCK_KEY = new StringBuilder("EventQueue.Lock");
144 public static final Object EVENT_QUEUE_COND_KEY = new StringBuilder("EventQueue.Condition");
145
259 // code is unaffected by the move to multiple AppContext ability.
260 AccessController.doPrivileged(new PrivilegedAction<Void>() {
261 public Void run() {
262 ThreadGroup currentThreadGroup =
263 Thread.currentThread().getThreadGroup();
264 ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
265 while (parentThreadGroup != null) {
266 // Find the root ThreadGroup to construct our main AppContext
267 currentThreadGroup = parentThreadGroup;
268 parentThreadGroup = currentThreadGroup.getParent();
269 }
270
271 mainAppContext = SunToolkit.createNewAppContext(currentThreadGroup);
272 return null;
273 }
274 });
275 }
276
277 /**
278 * Returns the appropriate AppContext for the caller,
279 * as determined by its ThreadGroup.
280 *
281 * @return the AppContext for the caller.
282 * @see java.lang.ThreadGroup
283 * @since 1.2
284 */
285 public static AppContext getAppContext() {
286 // we are standalone app, return the main app context
287 if (numAppContexts.get() == 1 && mainAppContext != null) {
288 return mainAppContext;
289 }
290
291 AppContext appContext = threadAppContext.get();
292
293 if (null == appContext) {
294 appContext = AccessController.doPrivileged(new PrivilegedAction<AppContext>()
295 {
296 public AppContext run() {
297 // Get the current ThreadGroup, and look for it and its
298 // parents in the hash from ThreadGroup to AppContext --
299 // it should be found, because we use createNewContext()
353
354 return context;
355 }
356 });
357 }
358
359 return appContext;
360 }
361
362 /**
363 * Returns true if the specified AppContext is the main AppContext.
364 *
365 * @param ctx the context to compare with the main context
366 * @return true if the specified AppContext is the main AppContext.
367 * @since 1.8
368 */
369 public static boolean isMainContext(AppContext ctx) {
370 return (ctx != null && ctx == mainAppContext);
371 }
372
373 private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout
374 // for disposal of all Frames
375 // (we wait for this time twice,
376 // once for dispose(), and once
377 // to clear the EventQueue).
378
379 private long THREAD_INTERRUPT_TIMEOUT = 1000;
380 // Default to 1-second timeout for all
381 // interrupted Threads to exit, and another
382 // 1 second for all stopped Threads to die.
383
384 /**
385 * Disposes of this AppContext, all of its top-level Frames, and
386 * all Threads and ThreadGroups contained within it.
387 *
388 * This method must be called from a Thread which is not contained
389 * within this AppContext.
390 *
391 * @exception IllegalThreadStateException if the current thread is
392 * contained within this AppContext
829 });
830 }
831
832 /**
833 * Returns the AppContext used for applet logging isolation, or null if
834 * the default global context can be used.
835 * If there's no applet, or if the caller is a stand alone application,
836 * or running in the main app context, returns null.
837 * Otherwise, returns the AppContext of the calling applet.
838 * @return null if the global default context can be used,
839 * an AppContext otherwise.
840 **/
841 public Object getAppletContext() {
842 // There's no AppContext: return null.
843 // No need to call getAppContext() if numAppContext == 0:
844 // it means that no AppContext has been created yet, and
845 // we don't want to trigger the creation of a main app
846 // context since we don't need it.
847 if (numAppContexts.get() == 0) return null;
848
849 AppContext ecx = null;
850
851 // Not sure we really need to re-check numAppContexts here.
852 // If all applets have gone away then we could have a
853 // numAppContexts coming back to 0. So we recheck
854 // it here because we don't want to trigger the
855 // creation of a main AppContext in that case.
856 // This is probably not 100% MT-safe but should reduce
857 // the window of opportunity in which that issue could
858 // happen.
859 if (numAppContexts.get() > 0) {
860 // Defaults to thread group caching.
861 // This is probably not required as we only really need
862 // isolation in a deployed applet environment, in which
863 // case ecx will not be null when we reach here
864 // However it helps emulate the deployed environment,
865 // in tests for instance.
866 ecx = ecx != null ? ecx : getAppContext();
867 }
868
869 // getAppletContext() may be called when initializing the main
|