How to prevent Java applications from creating tray icon?

With Ubuntu 13.04 the possibility to whitelist (and consequentely blacklist) certain applications from creating a tray icon is gone. Since then the tray icons of Java applications and Wine icons are hardcoded and always visible.

Although there are certain ppas, that provide a unity patch by giving back the systray.whitelist (not for 14.04 though, yet) I'd like to know if there are other ways to hide the tray-icons of java apps (e.g. JDownloader)

I know that there's a way in doing so for qt-applications by implementing apparmor-profiles that deny read access to the sni-qt package (e.g. for Skype, or Spotify)

Is there a way to implement apparmor profiles or something similar for Java applications and/or Wine applications?

thanks


Solution 1:

For Java Apps:

  • Actually for JDownloader case, It's a modular design. Tray icon comes as a plugin that can be disabled from:

    JDownloader → Addons → Addon Manager → Extensions → Uncheck Activate box for JD Light Tray

  • For Java applications general case, It is possible to use Java security manager by writing a custom policy rules.

    1. Create java.policy file in ~/.jdownloader contains:

      grant codeBase "file:/home/user/.jdownloader/-" {
      
      // full access
      //    permission java.security.AllPermission;
      
      // AWTPermission full or only selected elements from it
      //    permission java.awt.AWTPermission "*";
      
          permission java.awt.AWTPermission "accessClipboard";
          permission java.awt.AWTPermission "accessEventQueue";
      //    permission java.awt.AWTPermission "accessSystemTray";
          permission java.awt.AWTPermission "createRobot";
          permission java.awt.AWTPermission "fullScreenExclusive";
          permission java.awt.AWTPermission "listenToAllAWTEvents";
          permission java.awt.AWTPermission "readDisplayPixels";
          permission java.awt.AWTPermission "replaceKeyboardFocusManager";
          permission java.awt.AWTPermission "setAppletStub";
          permission java.awt.AWTPermission "setWindowAlwaysOnTop";
          permission java.awt.AWTPermission "showWindowWithoutWarningBanner";
          permission java.awt.AWTPermission "toolkitModality";
          permission java.awt.AWTPermission "watchMousePointer";
      
      // Added by try and learn
          permission java.io.FilePermission "/-", "read,write,delete";
          permission java.util.PropertyPermission "*", "read,write";
          permission java.util.logging.LoggingPermission "control";
          permission java.lang.RuntimePermission "*";
          permission java.net.NetPermission "*";
          permission java.security.SecurityPermission "*";
          permission javax.net.ssl.SSLPermission "*";
          permission java.net.SocketPermission "*", "connect,resolve";
          permission java.lang.reflect.ReflectPermission "*";
      };
      
    2. Modify jdownloader launch script to use custom policy

      sudo nano /usr/bin/jdownloader
      

      Add: -Djava.security.manager -Djava.security.policy=java.policy to java command call:

      exec java ${JAVA_OPTIONS}  -Djava.security.manager -Djava.security.policy=java.policy -jar JDownloader.jar $*
      

These are the minimum rules that allowed me to launch jdownloader. You may need to add more permissions. Because there is no deny option you have to write all needed grant rules.

References:

  • java.awt: Class SystemTray
  • java.awt: Class AWTPermission
  • java.security: Class BasicPermission

    See Direct Known Subclasses if you want to write a general template that grant AllPermission except accessSystemTray. So you can use it for all remaining java apps.

BTW, try to comment one of the rules by adding // to the beginning of line; So you can see how the error of denied permissions looks like. It tells you which permission you should to add. Also notice that I have used many - & * trying to extend rules as I'm looking for a quick solution (default was AllPermission anyway) and I'm not looking to jail the application.

Here is a template to start with, trying to grant all possible permissions:

grant codeBase "file:/home/user/.jdownloader/-" {

//    permission java.security.AllPermission;

//    permission java.awt.AWTPermission "*";

    permission java.awt.AWTPermission "accessClipboard";
    permission java.awt.AWTPermission "accessEventQueue";
//    permission java.awt.AWTPermission "accessSystemTray";
    permission java.awt.AWTPermission "createRobot";
    permission java.awt.AWTPermission "fullScreenExclusive";
    permission java.awt.AWTPermission "listenToAllAWTEvents";
    permission java.awt.AWTPermission "readDisplayPixels";
    permission java.awt.AWTPermission "replaceKeyboardFocusManager";
    permission java.awt.AWTPermission "setAppletStub";
    permission java.awt.AWTPermission "setWindowAlwaysOnTop";
    permission java.awt.AWTPermission "showWindowWithoutWarningBanner";
    permission java.awt.AWTPermission "toolkitModality";
    permission java.awt.AWTPermission "watchMousePointer";


    permission javax.sound.sampled.AudioPermission "*";
    permission javax.security.auth.AuthPermission "*";
//    permission javax.security.auth.kerberos.DelegationPermission "";
    permission javax.xml.bind.JAXBPermission "*";
    permission java.nio.file.LinkPermission "hard";
    permission java.nio.file.LinkPermission "symbolic";
    permission java.util.logging.LoggingPermission "control";
//    permission java.lang.management.ManagementPermission "*";
    permission javax.management.MBeanServerPermission "*";
    permission javax.management.MBeanTrustPermission "*";
    permission java.net.NetPermission "*";
    permission java.util.PropertyPermission "*", "read,write";
    permission java.lang.reflect.ReflectPermission "*";
    permission java.lang.RuntimePermission "*";
    permission java.security.SecurityPermission "*";
    permission java.io.SerializablePermission "*";
    permission java.sql.SQLPermission "*";
    permission javax.net.ssl.SSLPermission "*";
    permission javax.management.remote.SubjectDelegationPermission "*";
    permission javax.xml.ws.WebServicePermission "*";
//    permission  "*";

    permission java.io.FilePermission "/-", "read,write,execute,delete,readlink";
    permission javax.management.MBeanPermission "*", "*";
//    permission javax.security.auth.PrivateCredentialPermission "", "read";
    permission javax.security.auth.kerberos.ServicePermission "*", "initiate,accept";
    permission java.net.SocketPermission "*", "accept,connect,listen,resolve";
    permission java.net.URLPermission "*";
};

Note:

Java Policy Tools is a GUI tool to edit policy files. It make it more easy t find out all available options from drop box. It should be already install with Java package.

enter image description here

Solution 2:

Although Sneetshers answer is perfect I discovered a simpler (and obvious) solution. This approach works with JDownloader, but should also work with all other Java programs.

Just remove the logo rm ~/.jdownloader/jd/img/logo/jd_logo_128_128.png and afterwards create a invalid png icon with touch ~/.jdownloader/jd/img/logo/jd_logo_128_128.png

Using this approach, one can still use the TrayIcon plugin (useful for minimizing to tray) without the ugly java icon