2
0

Fixes #138- delays identicon update to avoid leaking interactive keyboard input.

This commit is contained in:
Maarten Billemont
2017-03-10 11:31:22 -05:00
parent c3f4d148a4
commit 77bee803b8
24 changed files with 188 additions and 70 deletions

View File

@@ -22,6 +22,9 @@ import com.google.common.io.*;
import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.lhunath.opal.system.util.TypeUtils;
import com.lyndir.masterpassword.gui.model.User;
import com.lyndir.masterpassword.gui.view.PasswordFrame;
import com.lyndir.masterpassword.gui.view.UnlockFrame;
import java.io.*;
import java.net.URI;
import java.net.URL;

View File

@@ -30,12 +30,16 @@ import javax.swing.*;
*/
public abstract class Res {
private static final WeakHashMap<Window, ExecutorService> executorByWindow = new WeakHashMap<>();
private static final Logger logger = Logger.get( Res.class );
private static final Colors colors = new Colors();
private static final WeakHashMap<Window, ScheduledExecutorService> executorByWindow = new WeakHashMap<>();
private static final Logger logger = Logger.get( Res.class );
private static final Colors colors = new Colors();
public static Future<?> execute(final Window host, final Runnable job) {
return getExecutor( host ).submit( new Runnable() {
return schedule( host, job, 0, TimeUnit.MILLISECONDS );
}
public static Future<?> schedule(final Window host, final Runnable job, final long delay, final TimeUnit timeUnit) {
return getExecutor( host ).schedule( new Runnable() {
@Override
public void run() {
try {
@@ -45,12 +49,16 @@ public abstract class Res {
logger.err( t, "Unexpected: %s", t.getLocalizedMessage() );
}
}
} );
}, delay, timeUnit );
}
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>() {
return schedule( host, job, 0, TimeUnit.MILLISECONDS );
}
public static <V> ListenableFuture<V> schedule(final Window host, final Callable<V> job, final long delay, final TimeUnit timeUnit) {
ScheduledExecutorService executor = getExecutor( host );
return JdkFutureAdapters.listenInPoolThread( executor.schedule( new Callable<V>() {
@Override
public V call()
throws Exception {
@@ -62,14 +70,14 @@ public abstract class Res {
throw t;
}
}
} ), executor );
}, delay, timeUnit ), executor );
}
private static ExecutorService getExecutor(final Window host) {
ExecutorService executor = executorByWindow.get( host );
private static ScheduledExecutorService getExecutor(final Window host) {
ScheduledExecutorService executor = executorByWindow.get( host );
if (executor == null) {
executorByWindow.put( host, executor = Executors.newSingleThreadExecutor() );
executorByWindow.put( host, executor = Executors.newSingleThreadScheduledExecutor() );
host.addWindowListener( new WindowAdapter() {
@Override
@@ -252,8 +260,8 @@ public abstract class Res {
public static class Colors {
private final Color frameBg = Color.decode( "#5A5D6B" );
private final Color controlBg = Color.decode( "#ECECEC" );
private final Color frameBg = Color.decode( "#5A5D6B" );
private final Color controlBg = Color.decode( "#ECECEC" );
private final Color controlBorder = Color.decode( "#BFBFBF" );
public Color frameBg() {

View File

@@ -1,4 +1,4 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.model;
import com.google.common.primitives.UnsignedInteger;
import com.lyndir.masterpassword.MPSiteType;

View File

@@ -1,4 +1,4 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.model;
import com.google.common.collect.ImmutableList;
import com.lyndir.masterpassword.model.IncorrectMasterPasswordException;

View File

@@ -1,4 +1,4 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.model;
import com.google.common.primitives.UnsignedInteger;
import com.lyndir.masterpassword.MPSiteType;

View File

@@ -1,8 +1,9 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.model;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.FluentIterable;
import com.lyndir.masterpassword.gui.*;
import com.lyndir.masterpassword.model.*;
import java.util.Arrays;
import javax.annotation.Nullable;
@@ -43,7 +44,7 @@ public class ModelUser extends User {
}
public void setAvatar(final int avatar) {
model.setAvatar(avatar % Res.avatars());
model.setAvatar( avatar % Res.avatars());
MPUserFileManager.get().save();
}

View File

@@ -1,4 +1,4 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.model;
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;

View File

@@ -1,4 +1,4 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.model;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;

View File

@@ -2,8 +2,8 @@ package com.lyndir.masterpassword.gui.platform.mac;
import com.apple.eawt.*;
import com.lyndir.masterpassword.gui.GUI;
import com.lyndir.masterpassword.gui.PasswordFrame;
import com.lyndir.masterpassword.gui.User;
import com.lyndir.masterpassword.gui.view.PasswordFrame;
import com.lyndir.masterpassword.gui.model.User;
import javax.swing.*;

View File

@@ -1,8 +1,10 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.view;
import com.google.common.collect.ImmutableList;
import com.lyndir.masterpassword.MPIdenticon;
import com.lyndir.masterpassword.gui.Res;
import com.lyndir.masterpassword.gui.model.User;
import com.lyndir.masterpassword.gui.util.Components;
import com.lyndir.masterpassword.gui.view.UnlockFrame;
import java.awt.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

View File

@@ -1,5 +1,8 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.view;
import com.lyndir.masterpassword.gui.Res;
import com.lyndir.masterpassword.gui.model.IncognitoUser;
import com.lyndir.masterpassword.gui.model.User;
import com.lyndir.masterpassword.gui.util.Components;
import java.awt.*;
import java.awt.event.ActionEvent;

View File

@@ -1,4 +1,4 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.view;
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
@@ -6,6 +6,8 @@ import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.*;
import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.masterpassword.gui.Res;
import com.lyndir.masterpassword.gui.model.ModelUser;
import com.lyndir.masterpassword.model.MPUser;
import com.lyndir.masterpassword.model.MPUserFileManager;
import com.lyndir.masterpassword.gui.util.Components;

View File

@@ -1,4 +1,4 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.view;
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
@@ -9,6 +9,8 @@ import com.google.common.collect.Iterables;
import com.google.common.primitives.UnsignedInteger;
import com.google.common.util.concurrent.*;
import com.lyndir.masterpassword.*;
import com.lyndir.masterpassword.gui.Res;
import com.lyndir.masterpassword.gui.model.*;
import com.lyndir.masterpassword.gui.util.Components;
import com.lyndir.masterpassword.gui.util.UnsignedIntegerModel;
import java.awt.*;

View File

@@ -1,12 +1,16 @@
package com.lyndir.masterpassword.gui;
package com.lyndir.masterpassword.gui.view;
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
import com.lyndir.masterpassword.MPIdenticon;
import com.lyndir.masterpassword.gui.*;
import com.lyndir.masterpassword.gui.model.User;
import com.lyndir.masterpassword.gui.util.Components;
import com.lyndir.masterpassword.model.IncorrectMasterPasswordException;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import javax.swing.*;
@@ -22,6 +26,7 @@ public class UnlockFrame extends JFrame {
private final JButton signInButton;
private final JPanel authenticationContainer;
private AuthenticationPanel authenticationPanel;
private Future<?> identiconFuture;
private boolean incognito;
public User user;
@@ -139,18 +144,34 @@ public class UnlockFrame extends JFrame {
}
boolean checkSignIn() {
if (identiconFuture != null)
identiconFuture.cancel( false );
identiconFuture = Res.schedule( this, new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
String fullName = user == null? "": user.getFullName();
char[] masterPassword = authenticationPanel.getMasterPassword();
if (fullName.isEmpty() || masterPassword.length == 0) {
identiconLabel.setText( " " );
return;
}
MPIdenticon identicon = new MPIdenticon( fullName, masterPassword );
identiconLabel.setText( identicon.getText() );
identiconLabel.setForeground(
Res.colors().fromIdenticonColor( identicon.getColor(), Res.Colors.BackgroundMode.DARK ) );
}
} );
}
}, 300, TimeUnit.MILLISECONDS );
String fullName = user == null? "": user.getFullName();
char[] masterPassword = authenticationPanel.getMasterPassword();
boolean enabled = !fullName.isEmpty() && masterPassword.length > 0;
if (fullName.isEmpty() || masterPassword.length == 0)
identiconLabel.setText( " " );
else {
MPIdenticon identicon = new MPIdenticon( fullName, masterPassword );
identiconLabel.setText( identicon.getText() );
identiconLabel.setForeground( Res.colors().fromIdenticonColor( identicon.getColor(), Res.Colors.BackgroundMode.DARK ) );
}
signInButton.setEnabled( enabled );
return enabled;
@@ -197,7 +218,7 @@ public class UnlockFrame extends JFrame {
} );
}
interface SignInCallback {
public interface SignInCallback {
void signedIn(User user);
}