changeset 1233:39e9fe259ce7

Remember panel extracted so it can be reused */netx/net/sourceforge/jnlp/security/SecurityDialogs.java: now correctly behaves on Xtrustall */netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java:result is using diamond */netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java:Simplified constructors, getting dialogue and jnlpfile is all they need */netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanel.java:extracted remember panel and related stuff. Made to use extracted one */netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/MatchingALACAttributePanel.java:same */netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java:same */netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/UnsignedAppletTrustWarningPanel.java:same */netx/net/sourceforge/jnlp/security/dialogs/remember/ActionChoiceListener.java:new class. Extracted stuff from AppTrustWarningPanel */netx/net/sourceforge/jnlp/security/dialogs/remember/AppSigningWarningAction.java:new class. Extracted stuff from AppTrustWarningPanel */netx/net/sourceforge/jnlp/security/dialogs/remember/RememberPanel.java:new class. Extracted stuff from AppTrustWarningPanel */tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java:minor, adapted to match current codebase
author Jiri Vanek <jvanek@redhat.com>
date Mon, 01 Jun 2015 14:43:43 +0200
parents fa266de1b2e7
children 9b3cfdc71c60
files ChangeLog netx/net/sourceforge/jnlp/security/SecurityDialogs.java netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanel.java netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/MatchingALACAttributePanel.java netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/UnsignedAppletTrustWarningPanel.java netx/net/sourceforge/jnlp/security/dialogs/remember/ActionChoiceListener.java netx/net/sourceforge/jnlp/security/dialogs/remember/AppSigningWarningAction.java netx/net/sourceforge/jnlp/security/dialogs/remember/RememberPanel.java tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java
diffstat 12 files changed, 351 insertions(+), 171 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed May 27 16:56:40 2015 +0200
+++ b/ChangeLog	Mon Jun 01 14:43:43 2015 +0200
@@ -1,3 +1,28 @@
+2015-06-01  Jiri Vanek  <jvanek@redhat.com>
+
+	Remember panel extracted so it can be reused
+	*/netx/net/sourceforge/jnlp/security/SecurityDialogs.java: now correctly behaves on Xtrustall
+	*/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java:
+	result is using diamond
+	*/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java:
+	Simplified constructors, getting dialogue and jnlpfile is all they need
+	*/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanel.java:
+	extracted remember panel and related stuff. Made to use extracted one
+	*/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/MatchingALACAttributePanel.java:
+	same
+	*/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java:
+	same
+	*/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/UnsignedAppletTrustWarningPanel.java:
+	same
+	*/netx/net/sourceforge/jnlp/security/dialogs/remember/ActionChoiceListener.java:
+	new class. Extracted stuff from AppTrustWarningPanel
+	*/netx/net/sourceforge/jnlp/security/dialogs/remember/AppSigningWarningAction.java:
+	new class. Extracted stuff from AppTrustWarningPanel
+	*/netx/net/sourceforge/jnlp/security/dialogs/remember/RememberPanel.java:
+	new class. Extracted stuff from AppTrustWarningPanel
+	*/tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java:
+	minor, adapted to match current codebase
+
 2015-05-27  Jiri Vanek  <jvanek@redhat.com>
 
 	Improved caching of files obtained via query
--- a/netx/net/sourceforge/jnlp/security/SecurityDialogs.java	Wed May 27 16:56:40 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/SecurityDialogs.java	Mon Jun 01 14:43:43 2015 +0200
@@ -59,7 +59,7 @@
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletTrustConfirmation;
 import static net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletTrustConfirmation.getStoredAction;
 import net.sourceforge.jnlp.security.dialogs.AccessWarningPaneComplexReturn;
-import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningPanel.AppSigningWarningAction;
+import net.sourceforge.jnlp.security.dialogs.remember.AppSigningWarningAction;
 import net.sourceforge.jnlp.util.UrlUtils;
 import net.sourceforge.jnlp.util.logging.OutputController;
 
@@ -234,7 +234,11 @@
     public static AppSigningWarningAction showUnsignedWarningDialog(JNLPFile file) {
 
         if (!shouldPromptUser()) {
-            return new AppSigningWarningAction(ExecuteAppletAction.NO, false);
+            if (JNLPRuntime.isTrustAll()) {
+                return new AppSigningWarningAction(ExecuteAppletAction.YES, false);
+            } else {
+                return new AppSigningWarningAction(ExecuteAppletAction.NO, false);
+            }
         }
 
         final SecurityDialogMessage message = new SecurityDialogMessage();
--- a/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java	Wed May 27 16:56:40 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java	Mon Jun 01 14:43:43 2015 +0200
@@ -50,9 +50,9 @@
 import net.sourceforge.jnlp.PluginBridge;
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
 import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate;
-import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningPanel.AppSigningWarningAction;
 import net.sourceforge.jnlp.security.CertVerifier;
 import net.sourceforge.jnlp.security.SecurityDialogs;
+import net.sourceforge.jnlp.security.dialogs.remember.AppSigningWarningAction;
 import net.sourceforge.jnlp.util.UrlUtils;
 import net.sourceforge.jnlp.util.logging.OutputController;
 
@@ -177,7 +177,7 @@
             return ((PluginBridge) file).getArchiveJars();
 
         List<JARDesc> jars = Arrays.asList(file.getResources().getJARs());
-        List<String> result = new ArrayList<String>();
+        List<String> result = new ArrayList<>();
         for (JARDesc jar : jars) {
             result.add(jar.getLocation().toString());
         }
--- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java	Wed May 27 16:56:40 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningDialog.java	Mon Jun 01 14:43:43 2015 +0200
@@ -40,14 +40,11 @@
 import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate;
 import net.sourceforge.jnlp.security.SecurityDialog;
 import net.sourceforge.jnlp.security.dialogs.SecurityDialogPanel;
-import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningPanel.ActionChoiceListener;
-import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningPanel.AppSigningWarningAction;
 
 /**
  * A panel that confirms that the user is OK with unsigned code running.
  */
 public class AppTrustWarningDialog extends SecurityDialogPanel {
-    private ActionChoiceListener listener;
 
     private AppTrustWarningDialog(final SecurityDialog dialog) {
         super(dialog);
@@ -55,37 +52,20 @@
 
     public static AppTrustWarningDialog unsigned(final SecurityDialog dialog, final JNLPFile file) {
         final AppTrustWarningDialog warningDialog = new AppTrustWarningDialog(dialog);
-        warningDialog.add(new UnsignedAppletTrustWarningPanel(dialog, file, warningDialog.getActionChoiceListener()));
+        warningDialog.add(new UnsignedAppletTrustWarningPanel(dialog, file));
         return warningDialog;
     }
 
     public static AppTrustWarningDialog partiallySigned(final SecurityDialog dialog, final JNLPFile file, final SecurityDelegate securityDelegate) {
         final AppTrustWarningDialog warningDialog = new AppTrustWarningDialog(dialog);
-        warningDialog.add(new PartiallySignedAppTrustWarningPanel(file, warningDialog.getActionChoiceListener(), dialog, securityDelegate));
+        warningDialog.add(new PartiallySignedAppTrustWarningPanel(file, dialog, securityDelegate));
         return warningDialog;
     }
     
     public static AppTrustWarningDialog matchingAlaca(SecurityDialog x, JNLPFile file, String codebase, String remoteUrls) {
         final AppTrustWarningDialog warningDialog = new AppTrustWarningDialog(x);
-        warningDialog.add(new MatchingALACAttributePanel(x, file, codebase, remoteUrls, warningDialog.getActionChoiceListener()));
+        warningDialog.add(new MatchingALACAttributePanel(x, file, codebase, remoteUrls));
         return warningDialog;
     }
 
-    private ActionChoiceListener getActionChoiceListener() {
-        if (listener == null) {
-            listener = createActionChoiceListener();
-        }
-        return listener;
-    }
-
-    private ActionChoiceListener createActionChoiceListener() {
-        return new ActionChoiceListener() {
-            @Override
-            public void actionChosen(final AppSigningWarningAction action) {
-                parent.setValue(action);
-                parent.dispose();
-            }
-        };
-    }
-
 }
--- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanel.java	Wed May 27 16:56:40 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanel.java	Mon Jun 01 14:43:43 2015 +0200
@@ -36,7 +36,6 @@
 
 package net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel;
 
-import static net.sourceforge.jnlp.runtime.Translator.R;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -44,7 +43,6 @@
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.Font;
-import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.IOException;
@@ -54,15 +52,12 @@
 
 import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
-import javax.swing.ButtonGroup;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
-import javax.swing.JCheckBox;
 import javax.swing.JDialog;
 import javax.swing.JEditorPane;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
-import javax.swing.JRadioButton;
 import javax.swing.SwingConstants;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
@@ -72,6 +67,7 @@
 import static net.sourceforge.jnlp.runtime.Translator.R;
 import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction;
 import net.sourceforge.jnlp.security.appletextendedsecurity.ExtendedAppletSecurityHelp;
+import net.sourceforge.jnlp.security.dialogs.remember.RememberPanel;
 import net.sourceforge.jnlp.util.ScreenFinder;
 import net.sourceforge.jnlp.util.logging.OutputController;
 
@@ -85,35 +81,6 @@
  */
 public abstract class AppTrustWarningPanel extends JPanel {
 
-    /*
-     * Details of decided action.
-     */
-    public static class AppSigningWarningAction {
-        private ExecuteAppletAction action;
-        private boolean applyToCodeBase;
-
-        public AppSigningWarningAction(ExecuteAppletAction action,
-                boolean applyToCodeBase) {
-            this.action = action;
-            this.applyToCodeBase = applyToCodeBase;
-        }
-
-        public ExecuteAppletAction getAction() {
-            return action;
-        }
-
-        public boolean rememberForCodeBase() {
-            return applyToCodeBase;
-        }
-    }
-
-    /*
-     * Callback for when action is decided.
-     */
-    public static interface ActionChoiceListener {
-        void actionChosen(AppSigningWarningAction action);
-    }
-
     protected int PANE_WIDTH = 500;
 
     protected int TOP_PANEL_HEIGHT = 60;
@@ -125,28 +92,27 @@
     protected JButton allowButton;
     protected JButton rejectButton;
     protected JButton helpButton;
-    protected JCheckBox permanencyCheckBox;
-    protected JRadioButton applyToAppletButton;
-    protected JRadioButton applyToCodeBaseButton;
+    protected RememberPanel rememberPanel;
+
 
     protected JNLPFile file;
 
-    protected ActionChoiceListener actionChoiceListener;
+
 
     /*
      * Subclasses should call addComponents() IMMEDIATELY after calling the super() constructor!
      */
-    public AppTrustWarningPanel(JNLPFile file, ActionChoiceListener actionChoiceListener) {
+    public AppTrustWarningPanel(JNLPFile file) {
         this.file = file;
-        this.actionChoiceListener = actionChoiceListener;
-        this.buttons = new ArrayList<JButton>();
+        rememberPanel = new RememberPanel(file.getCodeBase());
+        this.buttons = new ArrayList<>();
 
         allowButton = new JButton(R("ButProceed"));
         rejectButton = new JButton(R("ButCancel"));
         helpButton = new JButton(R("APPEXTSECguiPanelHelpButton"));
 
-        allowButton.addActionListener(chosenActionSetter(ExecuteAppletAction.YES));
-        rejectButton.addActionListener(chosenActionSetter(ExecuteAppletAction.NO));
+        allowButton.addActionListener(rememberPanel.chosenActionSetter(ExecuteAppletAction.YES));
+        rejectButton.addActionListener(rememberPanel.chosenActionSetter(ExecuteAppletAction.NO));
 
         helpButton.addActionListener(getHelpButtonAction());
 
@@ -196,9 +162,7 @@
         };
     }
 
-    protected static String htmlWrap(String text) {
-        return "<html>" + text + "</html>";
-    }
+
 
     private void setupTopPanel() {
         final String topLabelText = getTopPanelText();
@@ -237,7 +201,7 @@
         titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.BOLD, 18));
 
         String infoLabelText = getInfoPanelText();
-        JEditorPane infoLabel = new JEditorPane("text/html", htmlWrap(infoLabelText));
+        JEditorPane infoLabel = new JEditorPane("text/html", RememberPanel.htmlWrap(infoLabelText));
         infoLabel.setBackground(infoPanel.getBackground());
         infoLabel.setEditable(false);
         infoLabel.addHyperlinkListener(new HyperlinkListener() {
@@ -276,37 +240,7 @@
         add(questionPanel);
     }
 
-    private JPanel createMatchOptionsPanel() {
-        JPanel matchOptionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
-
-        ButtonGroup group = new ButtonGroup();
-        applyToAppletButton = new JRadioButton(R("SRememberAppletOnly"));
-        applyToAppletButton.setSelected(true);
-        applyToAppletButton.setEnabled(false); // Start disabled until 'Remember this option' is selected
-
-        applyToCodeBaseButton = new JRadioButton(htmlWrap(R("SRememberCodebase", file.getCodeBase())));
-        applyToCodeBaseButton.setEnabled(false);
-
-        group.add(applyToAppletButton);
-        group.add(applyToCodeBaseButton);
-
-        matchOptionsPanel.add(applyToAppletButton);
-        matchOptionsPanel.add(applyToCodeBaseButton);
-
-        return matchOptionsPanel;
-    }
-
-    private JPanel createCheckBoxPanel() {
-        JPanel checkBoxPanel = new JPanel(new BorderLayout());
-
-        permanencyCheckBox = new JCheckBox(htmlWrap(R("SRememberOption")));
-        permanencyCheckBox.addActionListener(permanencyListener());
-        checkBoxPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0));
-        checkBoxPanel.add(permanencyCheckBox,  BorderLayout.SOUTH);
-
-        return checkBoxPanel;
-    }
-
+   
     private JPanel createButtonPanel() {
         JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
 
@@ -322,11 +256,6 @@
     // Set up 'Remember Option' checkbox & Proceed/Cancel buttons
     private void setupButtonAndCheckBoxPanel() {
         JPanel outerPanel = new JPanel(new BorderLayout());
-        JPanel rememberPanel = new JPanel(new GridLayout(2 /*rows*/, 1 /*column*/));
-        rememberPanel.add(createMatchOptionsPanel());
-        rememberPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
-
-        outerPanel.add(createCheckBoxPanel(), BorderLayout.WEST);
         outerPanel.add(rememberPanel, BorderLayout.SOUTH);
         outerPanel.add(createButtonPanel(), BorderLayout.EAST);
 
@@ -346,34 +275,4 @@
         setupButtonAndCheckBoxPanel();
     }
 
-    // Toggles whether 'match applet' or 'match codebase' options are greyed out
-    protected ActionListener permanencyListener() {
-        return new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                applyToAppletButton.setEnabled(permanencyCheckBox.isSelected());
-                applyToCodeBaseButton.setEnabled(permanencyCheckBox.isSelected());
-            }
-        };
-    }
-
-    protected ActionListener chosenActionSetter(final ExecuteAppletAction action) {
-        return new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                ExecuteAppletAction realAction;
-
-                if (action == ExecuteAppletAction.YES) {
-                    realAction = permanencyCheckBox.isSelected() ? ExecuteAppletAction.ALWAYS : ExecuteAppletAction.YES;
-                } else if (action == ExecuteAppletAction.NO) {
-                    realAction = permanencyCheckBox.isSelected() ? ExecuteAppletAction.NEVER : ExecuteAppletAction.NO;
-                } else {
-                    realAction = action;
-                }
-
-                boolean applyToCodeBase = applyToCodeBaseButton.isSelected();
-                actionChoiceListener.actionChosen(new AppSigningWarningAction(realAction, applyToCodeBase));
-            }
-        };
-    }
 }
--- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/MatchingALACAttributePanel.java	Wed May 27 16:56:40 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/MatchingALACAttributePanel.java	Mon Jun 01 14:43:43 2015 +0200
@@ -54,6 +54,7 @@
 import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction;
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletActionEntry;
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletTrustConfirmation;
+import net.sourceforge.jnlp.security.dialogs.remember.RememberPanel;
 import net.sourceforge.jnlp.util.UrlUtils;
 
 /**
@@ -65,8 +66,8 @@
     private final String codebase;
     private final String remoteUrls;
 
-    public MatchingALACAttributePanel(SecurityDialog x, JNLPFile file, String codebase, String remoteUrls, ActionChoiceListener actionChoiceListener) {
-        super(file, actionChoiceListener);
+    public MatchingALACAttributePanel(SecurityDialog x, JNLPFile file, String codebase, String remoteUrls) {
+        super(file);
         this.title = super.getAppletTitle();
         this.codebase = codebase;
         this.remoteUrls = remoteUrls;
@@ -85,7 +86,7 @@
 
     @Override
     protected String getTopPanelText() {
-        return htmlWrap(Translator.R("ALACAMatchingMainTitle", title, codebase, remoteUrls));
+        return RememberPanel.htmlWrap(Translator.R("ALACAMatchingMainTitle", title, codebase, remoteUrls));
     }
 
     @Override
@@ -114,16 +115,10 @@
     }
 
     public static void main(String[] args) throws MalformedURLException, IOException, ParseException {
-        Set<URL> s = new HashSet<URL>();
+        Set<URL> s = new HashSet<>();
         s.add(new URL("http:/blah.com/blah"));
         s.add(new URL("http:/blah.com/blah/blah"));
-        MatchingALACAttributePanel w = new MatchingALACAttributePanel(null, new JNLPFile(new URL("http://www.geogebra.org/webstart/geogebra.jnlp")), "http://nbblah.url", UrlUtils.setOfUrlsToHtmlList(s), new ActionChoiceListener() {
-
-            @Override
-            public void actionChosen(AppSigningWarningAction action) {
-
-            }
-        });
+        MatchingALACAttributePanel w = new MatchingALACAttributePanel(null, new JNLPFile(new URL("http://www.geogebra.org/webstart/geogebra.jnlp")), "http://nbblah.url", UrlUtils.setOfUrlsToHtmlList(s));
         JFrame f = new JFrame();
         f.setSize(600, 400);
         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
--- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java	Wed May 27 16:56:40 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/PartiallySignedAppTrustWarningPanel.java	Mon Jun 01 14:43:43 2015 +0200
@@ -55,6 +55,7 @@
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletActionEntry;
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletTrustConfirmation;
 import net.sourceforge.jnlp.security.dialogs.TemporaryPermissionsButton;
+import net.sourceforge.jnlp.security.dialogs.remember.RememberPanel;
 import net.sourceforge.jnlp.tools.CertInformation;
 import net.sourceforge.jnlp.tools.JarCertVerifier;
 
@@ -64,15 +65,14 @@
     private final JButton sandboxButton;
     private final JButton advancedOptionsButton;
 
-    public PartiallySignedAppTrustWarningPanel(JNLPFile file, ActionChoiceListener actionChoiceListener,
-            SecurityDialog securityDialog, SecurityDelegate securityDelegate) {
-        super(file, actionChoiceListener);
+    public PartiallySignedAppTrustWarningPanel(JNLPFile file, SecurityDialog securityDialog, SecurityDelegate securityDelegate) {
+        super(file);
         this.jcv = (JarCertVerifier) securityDialog.getCertVerifier();
         this.INFO_PANEL_HEIGHT = 250;
 
         sandboxButton = new JButton();
         sandboxButton.setText(R("ButSandbox"));
-        sandboxButton.addActionListener(chosenActionSetter(ExecuteAppletAction.SANDBOX));
+        sandboxButton.addActionListener(rememberPanel.chosenActionSetter(ExecuteAppletAction.SANDBOX));
 
         advancedOptionsButton = new TemporaryPermissionsButton(file, securityDelegate, sandboxButton);
 
@@ -80,9 +80,7 @@
         buttons.add(2, advancedOptionsButton);
 
         addComponents();
-        if (securityDialog != null) {
-            securityDialog.setMinimumSize(new Dimension(600, 400));
-        }
+        securityDialog.setMinimumSize(new Dimension(600, 400));
     }
 
     private String getAppletInfo() {
@@ -142,7 +140,7 @@
 
     @Override
     protected String getTopPanelText() {
-        return htmlWrap(R(getTopPanelTextKey()));
+        return RememberPanel.htmlWrap(R(getTopPanelTextKey()));
     }
 
     @Override
@@ -159,12 +157,12 @@
                 text += "<br>" + R("SUnsignedRejectedBefore", rememberedEntry.getLocalisedTimeStamp());
             }
         }
-        return htmlWrap(text);
+        return RememberPanel.htmlWrap(text);
     }
 
     @Override
     protected String getQuestionPanelText() {
-        return htmlWrap(R(getQuestionPanelTextKey()));
+        return RememberPanel.htmlWrap(R(getQuestionPanelTextKey()));
     }
 
 }
--- a/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/UnsignedAppletTrustWarningPanel.java	Wed May 27 16:56:40 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/UnsignedAppletTrustWarningPanel.java	Mon Jun 01 14:43:43 2015 +0200
@@ -49,12 +49,13 @@
 import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction;
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletActionEntry;
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletTrustConfirmation;
+import net.sourceforge.jnlp.security.dialogs.remember.RememberPanel;
 
 
 public class UnsignedAppletTrustWarningPanel extends AppTrustWarningPanel {
 
-    public UnsignedAppletTrustWarningPanel(SecurityDialog securityDialog, final JNLPFile file, final ActionChoiceListener listener) {
-        super(file, listener);
+    public UnsignedAppletTrustWarningPanel(SecurityDialog securityDialog, final JNLPFile file) {
+        super(file);
         this.INFO_PANEL_HEIGHT = 250;
         addComponents();
         if (securityDialog != null) {
@@ -82,7 +83,7 @@
 
     @Override
     protected String getTopPanelText() {
-        return htmlWrap(R(getTopPanelTextKey()));
+        return RememberPanel.htmlWrap(R(getTopPanelTextKey()));
     }
 
     @Override
@@ -97,16 +98,16 @@
                 text += "<br>" + R("SUnsignedRejectedBefore", rememberedEntry.getLocalisedTimeStamp());
             }
         }
-        return htmlWrap(text);
+        return RememberPanel.htmlWrap(text);
     }
 
     @Override
     protected String getQuestionPanelText() {
-        return htmlWrap(R(getQuestionPanelTextKey()));
+        return RememberPanel.htmlWrap(R(getQuestionPanelTextKey()));
     }
     
     public static void main(String[] args) throws Exception {
-        UnsignedAppletTrustWarningPanel w = new UnsignedAppletTrustWarningPanel(null, new JNLPFile(new URL("http://www.geogebra.org/webstart/geogebra.jnlp")), null);
+        UnsignedAppletTrustWarningPanel w = new UnsignedAppletTrustWarningPanel(null, new JNLPFile(new URL("http://www.geogebra.org/webstart/geogebra.jnlp")));
         JFrame f = new JFrame();
         f.setSize(600, 400);
         f.add(w, BorderLayout.CENTER);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/security/dialogs/remember/ActionChoiceListener.java	Mon Jun 01 14:43:43 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2008-2010 Red Hat, Inc.
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2.
+
+ IcedTea 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING.  If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library.  Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on this library.  If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version.
+ */
+
+package net.sourceforge.jnlp.security.dialogs.remember;
+
+/*
+ * Callback for when action is decided.
+ */
+public interface ActionChoiceListener {
+
+    void actionChosen(AppSigningWarningAction action);
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/security/dialogs/remember/AppSigningWarningAction.java	Mon Jun 01 14:43:43 2015 +0200
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 2008-2010 Red Hat, Inc.
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2.
+
+ IcedTea 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING.  If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library.  Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on this library.  If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version.
+ */
+package net.sourceforge.jnlp.security.dialogs.remember;
+
+import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction;
+
+/*
+ * Details of decided action.
+ */
+public class AppSigningWarningAction {
+    private final ExecuteAppletAction action;
+    private final boolean applyToCodeBase;
+
+    public AppSigningWarningAction(ExecuteAppletAction action, boolean applyToCodeBase) {
+        this.action = action;
+        this.applyToCodeBase = applyToCodeBase;
+    }
+
+    public ExecuteAppletAction getAction() {
+        return action;
+    }
+
+    public boolean rememberForCodeBase() {
+        return applyToCodeBase;
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/security/dialogs/remember/RememberPanel.java	Mon Jun 01 14:43:43 2015 +0200
@@ -0,0 +1,171 @@
+/*
+ Copyright (C) 2008-2010 Red Hat, Inc.
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2.
+
+ IcedTea 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING.  If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library.  Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on this library.  If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version.
+ */
+package net.sourceforge.jnlp.security.dialogs.remember;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.URL;
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBox;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import static net.sourceforge.jnlp.runtime.Translator.R;
+import net.sourceforge.jnlp.security.SecurityDialog;
+import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction;
+
+public class RememberPanel extends JPanel {
+
+    protected JCheckBox permanencyCheckBox;
+    protected JRadioButton applyToAppletButton;
+    protected JRadioButton applyToCodeBaseButton;
+    private final URL codebase;
+    protected ActionChoiceListener actionChoiceListener;
+
+    public RememberPanel(URL codebase) {
+        super(new GridLayout(2 /*rows*/, 1 /*column*/));
+        this.codebase = codebase;
+        this.actionChoiceListener = getActionChoiceListener();
+        this.add(createCheckBoxPanel(), BorderLayout.WEST);
+        this.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
+        this.add(createMatchOptionsPanel());
+        this.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
+
+    }
+
+    private JPanel createCheckBoxPanel() {
+        JPanel checkBoxPanel = new JPanel(new BorderLayout());
+
+        permanencyCheckBox = new JCheckBox(htmlWrap(R("SRememberOption")));
+        permanencyCheckBox.addActionListener(permanencyListener());
+        checkBoxPanel.add(permanencyCheckBox, BorderLayout.SOUTH);
+
+        return checkBoxPanel;
+    }
+
+    private JPanel createMatchOptionsPanel() {
+        JPanel matchOptionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+
+        ButtonGroup group = new ButtonGroup();
+        applyToAppletButton = new JRadioButton(R("SRememberAppletOnly"));
+        applyToAppletButton.setSelected(true);
+        applyToAppletButton.setEnabled(false); // Start disabled until 'Remember this option' is selected
+
+        applyToCodeBaseButton = new JRadioButton(htmlWrap(R("SRememberCodebase", codebase)));
+        applyToCodeBaseButton.setEnabled(false);
+
+        group.add(applyToAppletButton);
+        group.add(applyToCodeBaseButton);
+
+        matchOptionsPanel.add(applyToAppletButton);
+        matchOptionsPanel.add(applyToCodeBaseButton);
+
+        return matchOptionsPanel;
+    }
+
+    public static String htmlWrap(String text) {
+        return "<html>" + text + "</html>";
+    }
+
+    // Toggles whether 'match applet' or 'match codebase' options are greyed out
+    protected ActionListener permanencyListener() {
+        return new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                applyToAppletButton.setEnabled(permanencyCheckBox.isSelected());
+                applyToCodeBaseButton.setEnabled(permanencyCheckBox.isSelected());
+            }
+        };
+    }
+
+    public boolean isAlwaysSelected() {
+        return permanencyCheckBox.isSelected();
+    }
+
+    public boolean isCodebaseSelected() {
+        return applyToCodeBaseButton.isSelected();
+    }
+
+    public ActionListener chosenActionSetter(final ExecuteAppletAction action) {
+        return new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                ExecuteAppletAction realAction;
+
+                if (action == ExecuteAppletAction.YES) {
+                    realAction = isAlwaysSelected() ? ExecuteAppletAction.ALWAYS : ExecuteAppletAction.YES;
+                } else if (action == ExecuteAppletAction.NO) {
+                    realAction = isAlwaysSelected() ? ExecuteAppletAction.NEVER : ExecuteAppletAction.NO;
+                } else {
+                    realAction = action;
+                }
+
+                boolean applyToCodeBase = isCodebaseSelected();
+                actionChoiceListener.actionChosen(new AppSigningWarningAction(realAction, applyToCodeBase));
+            }
+        };
+    }
+
+    private ActionChoiceListener getActionChoiceListener() {
+        if (actionChoiceListener == null) {
+            actionChoiceListener = createActionChoiceListener();
+        }
+        return actionChoiceListener;
+    }
+
+    private ActionChoiceListener createActionChoiceListener() {
+        return new ActionChoiceListener() {
+            @Override
+            public void actionChosen(final AppSigningWarningAction action) {
+                //in this moment, panel is placed on some dialogue
+                Container p = RememberPanel.this.getParent();
+                while (p != null) {
+                    if (p instanceof SecurityDialog) {
+                        ((SecurityDialog) p).setValue(action);
+                        ((SecurityDialog) p).dispose();
+                        break;
+                    }
+                    p = p.getParent();
+                }
+            }
+        };
+    }
+}
--- a/tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java	Wed May 27 16:56:40 2015 +0200
+++ b/tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java	Mon Jun 01 14:43:43 2015 +0200
@@ -1,7 +1,5 @@
 package net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel;
 
-import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.UnsignedAppletTrustWarningPanel;
-import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningPanel;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -10,6 +8,7 @@
 import javax.swing.JButton;
 import net.sourceforge.jnlp.PluginBridge;
 import net.sourceforge.jnlp.PluginParameters;
+import net.sourceforge.jnlp.security.dialogs.remember.RememberPanel;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -48,7 +47,7 @@
         mockPluginBridge = new PluginBridge(mockCodebase, mockDocumentBase, mockJar,
                 mockMainClass, mockWidth, mockHeight, mockParameters);
 
-        panelList.add(new UnsignedAppletTrustWarningPanel(null, mockPluginBridge, null));
+        panelList.add(new UnsignedAppletTrustWarningPanel(null, mockPluginBridge));
     }
 
     @Test
@@ -109,7 +108,7 @@
     public void testHtmlWrap() throws Exception {
         final String testText = "This is some text";
         final String expectedResult = "<html>This is some text</html>";
-        final String actualResult = UnsignedAppletTrustWarningPanel.htmlWrap(testText);
+        final String actualResult = RememberPanel.htmlWrap(testText);
         assertEquals("htmlWrap should properly wrap text with HTML tags", expectedResult, actualResult);
     }