Just dispose on close and scope executors to a window, clean up on window hide.
This commit is contained in:
parent
80f507b4cc
commit
d1649f3c33
@ -116,9 +116,6 @@ public class GUI implements UnlockFrame.SignInCallback {
|
||||
}
|
||||
|
||||
protected PasswordFrame newPasswordFrame(final User user) {
|
||||
PasswordFrame frame = new PasswordFrame( user );
|
||||
frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
|
||||
|
||||
return frame;
|
||||
return new PasswordFrame( user );
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ public class ModelUser extends User {
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
|
||||
masterPassword = null;
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
site.setSiteCounter( siteCounter );
|
||||
}
|
||||
|
||||
ListenableFuture<String> passwordFuture = Res.execute( new Callable<String>() {
|
||||
ListenableFuture<String> passwordFuture = Res.execute( this, new Callable<String>() {
|
||||
@Override
|
||||
public String call()
|
||||
throws Exception {
|
||||
|
@ -8,9 +8,11 @@ import com.google.common.io.Resources;
|
||||
import com.google.common.util.concurrent.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -22,8 +24,8 @@ import javax.swing.*;
|
||||
*/
|
||||
public abstract class Res {
|
||||
|
||||
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
private static final Logger logger = Logger.get( Res.class );
|
||||
private static final WeakHashMap<Window, ExecutorService> executorByWindow = new WeakHashMap<>();
|
||||
private static final Logger logger = Logger.get( Res.class );
|
||||
|
||||
private static Font sourceCodeProRegular;
|
||||
private static Font sourceCodeProBlack;
|
||||
@ -32,8 +34,8 @@ public abstract class Res {
|
||||
private static Font exoRegular;
|
||||
private static Font exoThin;
|
||||
|
||||
public static Future<?> execute(final Runnable job) {
|
||||
return executor.submit( new Runnable() {
|
||||
public static Future<?> execute(final Window host, final Runnable job) {
|
||||
return getExecutor( host ).submit( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
@ -46,7 +48,8 @@ public abstract class Res {
|
||||
} );
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> execute(final Callable<V> job) {
|
||||
public static <V> ListenableFuture<V> execute(final Window host, final Callable<V> job) {
|
||||
ExecutorService executor = getExecutor( host );
|
||||
return JdkFutureAdapters.listenInPoolThread( executor.submit( new Callable<V>() {
|
||||
@Override
|
||||
public V call()
|
||||
@ -62,6 +65,25 @@ public abstract class Res {
|
||||
} ), executor );
|
||||
}
|
||||
|
||||
private static ExecutorService getExecutor(final Window host) {
|
||||
ExecutorService executor = executorByWindow.get( host );
|
||||
|
||||
if (executor == null) {
|
||||
executorByWindow.put( host, executor = Executors.newSingleThreadExecutor() );
|
||||
|
||||
host.addWindowListener( new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(final WindowEvent e) {
|
||||
ExecutorService executor = executorByWindow.remove( host );
|
||||
if (executor != null)
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
return executor;
|
||||
}
|
||||
|
||||
public static Icon iconAdd() {
|
||||
return new RetinaIcon( Resources.getResource( "media/icon_add@2x.png" ) );
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ public class UnlockFrame extends JFrame {
|
||||
signInButton.setEnabled( false );
|
||||
signInButton.setText( "Signing In..." );
|
||||
|
||||
Res.execute( new Runnable() {
|
||||
Res.execute( this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean success = signInCallback.signedIn( user );
|
||||
|
@ -101,6 +101,7 @@
|
||||
<p>Another strategy is by "encoding" something you already know. This can seem like a good way to make memorable passwords, but recalling the "encoding" you used two years later can be tricky. This also makes it much easier for attackers that know you to find your password.</p>
|
||||
<p>Master Password itself generates very random passwords that look semi-legible, for instance <code>Togu3]ToxiBuzb</code>. Such passwords have been found to be very memorable while also being very high in entropy (hard to guess).</p>
|
||||
<p>A strategy that's gaining traction lately is that of combining words into a sentence. Some claim it's best for the sentence to make no grammatical sense, others dispute these claims. It's a fact, though, that if your attacker doesn't expect such a password, they're nearly impossible to defeat.</p>
|
||||
<p><iframe width="420" height="315" src="//www.youtube.com/embed/MSyIhapMdI8?start=109" frameborder="0" allowfullscreen></iframe></p>
|
||||
<p>Let's sum these strategies up in a table, note that this type of comparison is very subjective.</p>
|
||||
<table>
|
||||
<caption>Time to crack a master password</caption>
|
||||
|
Loading…
Reference in New Issue
Block a user