mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-127343 Pass ModalityState to PasswordSafe.getPassword
Since PasswordSafe.getPassword may request for the master password, and since this request can be made from any thread, it needs the proper ModalityState to execute invokeAndWait(), otherwise the master password dialog won't appear above some modal progresses which requested the password, just like in IDEA-127343. => * Deprecate the existing getPassword() and create new one accepting ModalityState. * Pass the ModalityState down to the MasterKeyPasswordSafe#key which actually shows the dialog. * Some providers (like Nil or Memory) can safely ignore the modality state, since they don't show any dialogs.
This commit is contained in:
@@ -41,9 +41,16 @@ public interface PasswordStorage {
|
||||
* @return the stored password or null if the password record was not found or was removed
|
||||
* @throws PasswordSafeException if password safe cannot be accessed
|
||||
* @throws IllegalStateException if the method is called from the read action.
|
||||
*
|
||||
* @deprecated To remove in IDEA 15. Use {@link #getPassword(Project, Class, String, ModalityState)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
|
||||
|
||||
@Nullable
|
||||
String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
|
||||
@Nullable ModalityState state) throws PasswordSafeException;
|
||||
/**
|
||||
* Remove password stored in a password safe
|
||||
*
|
||||
|
||||
+11
-3
@@ -22,6 +22,7 @@ import com.intellij.ide.passwordSafe.impl.providers.masterKey.MasterKeyPasswordS
|
||||
import com.intellij.ide.passwordSafe.impl.providers.masterKey.PasswordDatabase;
|
||||
import com.intellij.ide.passwordSafe.impl.providers.memory.MemoryPasswordSafe;
|
||||
import com.intellij.ide.passwordSafe.impl.providers.nil.NilProvider;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -71,10 +72,17 @@ public class PasswordSafeImpl extends PasswordSafe {
|
||||
|
||||
@Nullable
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
|
||||
return getPassword(project, requester, key, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requester, String key,
|
||||
@Nullable ModalityState modalityState) throws PasswordSafeException {
|
||||
if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
|
||||
String password = getMemoryProvider().getPassword(project, requester, key);
|
||||
String password = getMemoryProvider().getPassword(project, requester, key, modalityState);
|
||||
if (password == null) {
|
||||
password = provider().getPassword(project, requester, key);
|
||||
password = provider().getPassword(project, requester, key, modalityState);
|
||||
if (password != null) {
|
||||
// cache the password in memory as well for easier access during the session
|
||||
getMemoryProvider().storePassword(project, requester, key, password);
|
||||
@@ -82,7 +90,7 @@ public class PasswordSafeImpl extends PasswordSafe {
|
||||
}
|
||||
return password;
|
||||
}
|
||||
return provider().getPassword(project, requester, key);
|
||||
return provider().getPassword(project, requester, key, modalityState);
|
||||
}
|
||||
|
||||
public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
|
||||
|
||||
+11
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
package com.intellij.ide.passwordSafe.impl;
|
||||
|
||||
import com.intellij.ide.passwordSafe.PasswordSafeException;
|
||||
import com.intellij.ide.passwordSafe.PasswordStorage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The provider for password safe component
|
||||
@@ -34,4 +38,11 @@ public abstract class PasswordSafeProvider implements PasswordStorage {
|
||||
* @return the name of provider
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
|
||||
return getPassword(project, requestor, key, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-9
@@ -43,13 +43,15 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
|
||||
* @throws PasswordSafeException in case of problems with access to the password database.
|
||||
* @throws IllegalStateException if the method is called from the read action.
|
||||
*/
|
||||
protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor) throws PasswordSafeException;
|
||||
protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor,
|
||||
@Nullable ModalityState modalityState) throws PasswordSafeException;
|
||||
|
||||
@Nullable
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
|
||||
byte[] k = dbKey(project, requestor, key);
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
|
||||
@Nullable ModalityState modalityState) throws PasswordSafeException {
|
||||
byte[] k = dbKey(project, requestor, key, modalityState);
|
||||
byte[] ct = getEncryptedPassword(k);
|
||||
return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor), ct);
|
||||
return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor, modalityState), ct);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,14 +68,16 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
|
||||
* @param project
|
||||
* @param requestor the requestor class
|
||||
* @param key the key to use
|
||||
* @param modalityState
|
||||
* @return the key to use for map
|
||||
*/
|
||||
private byte[] dbKey(@Nullable Project project, Class requestor, String key) throws PasswordSafeException {
|
||||
return EncryptionUtil.dbKey(key(project, requestor), requestor, key);
|
||||
private byte[] dbKey(@Nullable Project project, @NotNull Class requestor, String key,
|
||||
@Nullable ModalityState modalityState) throws PasswordSafeException {
|
||||
return EncryptionUtil.dbKey(key(project, requestor, modalityState), requestor, key);
|
||||
}
|
||||
|
||||
public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
|
||||
byte[] k = dbKey(project, requester, key);
|
||||
byte[] k = dbKey(project, requester, key, null);
|
||||
removeEncryptedPassword(k);
|
||||
}
|
||||
|
||||
@@ -85,8 +89,8 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
|
||||
protected abstract void removeEncryptedPassword(byte[] key);
|
||||
|
||||
public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
|
||||
byte[] k = dbKey(project, requestor, key);
|
||||
byte[] ct = EncryptionUtil.encryptText(key(project, requestor), value);
|
||||
byte[] k = dbKey(project, requestor, key, null);
|
||||
byte[] ct = EncryptionUtil.encryptText(key(project, requestor, null), value);
|
||||
storeEncryptedPassword(k, ct);
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -154,7 +154,8 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) throws PasswordSafeException {
|
||||
protected byte[] key(@Nullable final Project project, @NotNull final Class requestor,
|
||||
@Nullable ModalityState modalityState) throws PasswordSafeException {
|
||||
Application application = ApplicationManager.getApplication();
|
||||
if (!isTestMode() && application.isHeadlessEnvironment()) {
|
||||
throw new MasterPasswordUnavailableException("The provider is not available in headless environment");
|
||||
@@ -199,7 +200,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, ModalityState.defaultModalityState());
|
||||
}, modalityState == null ? ModalityState.defaultModalityState() : modalityState);
|
||||
//noinspection ThrowableResultOfMethodCallIgnored
|
||||
if (ex.get() != null) {
|
||||
throw ex.get();
|
||||
@@ -210,11 +211,12 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
|
||||
@Nullable ModalityState modalityState) throws PasswordSafeException {
|
||||
if (database.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return super.getPassword(project, requestor, key);
|
||||
return super.getPassword(project, requestor, key, modalityState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-1
@@ -19,10 +19,12 @@ import com.intellij.ide.passwordSafe.impl.PasswordSafeTimed;
|
||||
import com.intellij.ide.passwordSafe.impl.providers.BasePasswordSafeProvider;
|
||||
import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper;
|
||||
import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collections;
|
||||
@@ -63,7 +65,7 @@ public class MemoryPasswordSafe extends BasePasswordSafeProvider {
|
||||
* @return the secret key used by provider
|
||||
*/
|
||||
@Override
|
||||
protected byte[] key(Project project, @NotNull Class requestor) {
|
||||
protected byte[] key(Project project, @NotNull Class requestor, @Nullable ModalityState modalityState) {
|
||||
if (key.get() == null) {
|
||||
byte[] rnd = new byte[EncryptionUtil.SECRET_KEY_SIZE_BYTES * 16];
|
||||
new SecureRandom().nextBytes(rnd);
|
||||
|
||||
+4
-1
@@ -17,6 +17,7 @@ package com.intellij.ide.passwordSafe.impl.providers.nil;
|
||||
|
||||
import com.intellij.ide.passwordSafe.PasswordSafeException;
|
||||
import com.intellij.ide.passwordSafe.impl.PasswordSafeProvider;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -41,7 +42,9 @@ public final class NilProvider extends PasswordSafeProvider {
|
||||
return "Do not Store";
|
||||
}
|
||||
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
|
||||
@Nullable
|
||||
public String getPassword(@Nullable Project project, @NotNull Class requester, String key,
|
||||
@Nullable ModalityState modalityState) throws PasswordSafeException {
|
||||
// nothing is stored
|
||||
return null;
|
||||
}
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
|
||||
ps.removePassword(project, requestor, key);
|
||||
}
|
||||
else {
|
||||
String pw = ps.getPassword(project, requestor, key);
|
||||
String pw = ps.getPassword(project, requestor, key, modalityState);
|
||||
if (pw != null) {
|
||||
return pw;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
|
||||
return "";
|
||||
}
|
||||
url = adjustUrl(url);
|
||||
Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url);
|
||||
Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url, myModalityState);
|
||||
if (authData != null && authData.second.getPassword() != null) {
|
||||
String password = authData.second.getPassword();
|
||||
myDataProvider = authData.first;
|
||||
@@ -114,7 +114,7 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
|
||||
@NotNull
|
||||
public String askUsername(@NotNull String url) {
|
||||
url = adjustUrl(url);
|
||||
Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url);
|
||||
Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url, myModalityState);
|
||||
String login = null;
|
||||
String password = null;
|
||||
if (authData != null) {
|
||||
@@ -223,10 +223,10 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
|
||||
|
||||
// return the first that knows username + password; otherwise return the first that knows just the username
|
||||
@Nullable
|
||||
private Pair<GitHttpAuthDataProvider, AuthData> findBestAuthData(@NotNull String url) {
|
||||
private Pair<GitHttpAuthDataProvider, AuthData> findBestAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
|
||||
Pair<GitHttpAuthDataProvider, AuthData> candidate = null;
|
||||
for (GitHttpAuthDataProvider provider : getProviders()) {
|
||||
AuthData data = provider.getAuthData(url);
|
||||
AuthData data = provider.getAuthData(url, modalityState);
|
||||
if (data != null) {
|
||||
Pair<GitHttpAuthDataProvider, AuthData> pair = Pair.create(provider, data);
|
||||
if (data.getPassword() != null) {
|
||||
@@ -268,12 +268,12 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AuthData getAuthData(@NotNull String url) {
|
||||
public AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
|
||||
String userName = getUsername(url);
|
||||
String key = makeKey(url, userName);
|
||||
final PasswordSafe passwordSafe = PasswordSafe.getInstance();
|
||||
try {
|
||||
String password = passwordSafe.getPassword(myProject, PASS_REQUESTER, key);
|
||||
String password = passwordSafe.getPassword(myProject, PASS_REQUESTER, key, modalityState);
|
||||
return new AuthData(StringUtil.notNullize(userName), password);
|
||||
}
|
||||
catch (PasswordSafeException e) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.remote;
|
||||
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.util.AuthData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -31,7 +32,7 @@ public interface GitHttpAuthDataProvider {
|
||||
ExtensionPointName<GitHttpAuthDataProvider> EP_NAME = ExtensionPointName.create("Git4Idea.GitHttpAuthDataProvider");
|
||||
|
||||
@Nullable
|
||||
AuthData getAuthData(@NotNull String url);
|
||||
AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState);
|
||||
|
||||
void forgetPassword(@NotNull String url);
|
||||
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.github.extensions;
|
||||
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.AuthData;
|
||||
import git4idea.remote.GitHttpAuthDataProvider;
|
||||
@@ -31,7 +32,7 @@ public class GithubHttpAuthDataProvider implements GitHttpAuthDataProvider {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AuthData getAuthData(@NotNull String url) {
|
||||
public AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
|
||||
if (!GithubUrlUtil.isGithubUrl(url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user