[github] Stop progress to show not-trusted cert warning

Problem:
If a Mac Message dialog is shown when under modal progress, it becomes
non-clickable.

To avoid it:
move the dialog asking about non-trusted SSL certificate "upwards":
  * catch the SSL exception right in the accessWithModalProgress(),
  * finish the modal task,
  * ask if user trusts the host,
  * retry the task (and start another modal progress).
This commit is contained in:
Kirill Likhodedov
2013-02-20 20:29:33 +04:00
parent badbee00b1
commit 1f9da6f1a1
3 changed files with 47 additions and 30 deletions
@@ -122,7 +122,7 @@ public class GithubShareAction extends DumbAwareAction {
final GithubSettings settings = GithubSettings.getInstance();
final String password = settings.getPassword();
final Boolean privateRepoAllowed =
GithubUtil.accessToGithubWithModalProgress(project, new ThrowableComputable<Boolean, IOException>() {
GithubUtil.accessToGithubWithModalProgress(project, settings.getHost(), new ThrowableComputable<Boolean, IOException>() {
@Override
public Boolean compute() throws IOException {
ProgressManager.getInstance().getProgressIndicator().setText("Trying to login to GitHub");
@@ -15,11 +15,9 @@
*/
package org.jetbrains.plugins.github;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.CalledInAwt;
import com.intellij.util.ThrowableConvertor;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
@@ -79,12 +77,11 @@ public class GithubSslSupport {
@NotNull HttpClient client, @NotNull URI uri,
@NotNull ThrowableConvertor<String, HttpMethod, IOException> methodCreator)
throws IOException {
if (!(e.getCause() instanceof ValidatorException)) {
if (!isCertificateException(e)) {
throw e;
}
boolean proceed = isTrusted(host) || askIfShouldProceed(host);
if (proceed) {
if (isTrusted(host)) {
// creating a special configuration that allows connections to non-trusted HTTPS hosts
// see the javadoc to EasySSLProtocolSocketFactory for details
Protocol easyHttps = new Protocol("https", (ProtocolSocketFactory)new EasySSLProtocolSocketFactory(), 443);
@@ -96,10 +93,13 @@ public class GithubSslSupport {
// and changing host by hands (HttpMethodBase#setHostConfiguration) is deprecated.
HttpMethod method = methodCreator.convert(relativeUri);
client.executeMethod(hc, method);
saveToTrusted(host);
return method;
}
return null;
throw e;
}
public static boolean isCertificateException(IOException e) {
return e.getCause() instanceof ValidatorException;
}
private static boolean isTrusted(@NotNull String host) {
@@ -110,19 +110,17 @@ public class GithubSslSupport {
GithubSettings.getInstance().addTrustedHost(host);
}
private static boolean askIfShouldProceed(final String host) {
@CalledInAwt
public boolean askIfShouldProceed(final String host) {
final String BACK_TO_SAFETY = "No, I don't trust";
final String RISK = "Proceed anyway";
final Ref<Integer> choice = new Ref<Integer>(-1);
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
choice.set(Messages.showDialog("The security certificate of " + host + " is not trusted. Do you want to proceed anyway?",
"Not Trusted Certificate", new String[]{BACK_TO_SAFETY, RISK}, 0, Messages.getErrorIcon()));
}
}, ModalityState.defaultModalityState());
return choice.get() == 1;
final String TRUST = "Proceed anyway";
int choice = Messages.showDialog("The security certificate of " + host + " is not trusted. Do you want to proceed anyway?",
"Not Trusted Certificate", new String[] { BACK_TO_SAFETY, TRUST }, 0, Messages.getErrorIcon());
boolean trust = (choice == 1);
if (trust) {
saveToTrusted(host);
}
return trust;
}
}
@@ -63,12 +63,29 @@ public class GithubUtil {
return "https://" + GithubSettings.getInstance().getHost();
}
/**
* @deprecated TODO Use background progress
*/
@Deprecated
public static <T> T accessToGithubWithModalProgress(@NotNull final Project project,
@Nullable
public static <T> T accessToGithubWithModalProgress(@NotNull final Project project, @NotNull String host,
@NotNull final ThrowableComputable<T, IOException> computable) throws IOException {
try {
return doAccessToGithubWithModalProgress(project, computable);
}
catch (IOException e) {
GithubSslSupport sslSupport = GithubSslSupport.getInstance();
if (GithubSslSupport.isCertificateException(e)) {
if (sslSupport.askIfShouldProceed(host)) {
// retry with the host being already trusted
return doAccessToGithubWithModalProgress(project, computable);
}
else {
return null;
}
}
throw e;
}
}
private static <T> T doAccessToGithubWithModalProgress(@NotNull final Project project,
@NotNull final ThrowableComputable<T, IOException> computable) throws IOException {
final Ref<T> result = new Ref<T>();
final Ref<IOException> exception = new Ref<IOException>();
ProgressManager.getInstance().run(new Task.Modal(project, "Access to GitHub", true) {
@@ -227,13 +244,14 @@ public class GithubUtil {
if (StringUtil.isEmptyOrSpaces(url) || StringUtil.isEmptyOrSpaces(login) || StringUtil.isEmptyOrSpaces(password)){
return false;
}
return accessToGithubWithModalProgress(project, new ThrowableComputable<Boolean, IOException>() {
Boolean result = accessToGithubWithModalProgress(project, url, new ThrowableComputable<Boolean, IOException>() {
@Override
public Boolean compute() throws IOException {
ProgressManager.getInstance().getProgressIndicator().setText("Trying to login to GitHub");
return testConnection(url, login, password);
}
});
return result == null ? false : result;
}
/**
@@ -254,7 +272,7 @@ public class GithubUtil {
// Otherwise our credentials are valid and they are successfully stored in settings
final GithubSettings settings = GithubSettings.getInstance();
final String validPassword = settings.getPassword();
return accessToGithubWithModalProgress(project, new ThrowableComputable<List<RepositoryInfo>, IOException>() {
return accessToGithubWithModalProgress(project, settings.getHost(), new ThrowableComputable<List<RepositoryInfo>, IOException>() {
@Override
public List<RepositoryInfo> compute() throws IOException {
ProgressManager.getInstance().getProgressIndicator().setText("Extracting info about available repositories");
@@ -272,7 +290,8 @@ public class GithubUtil {
public static RepositoryInfo getDetailedRepositoryInfo(final Project project, final String owner, final String name) throws IOException {
final GithubSettings settings = GithubSettings.getInstance();
final String password = settings.getPassword();
final Boolean validCredentials = accessToGithubWithModalProgress(project, new ThrowableComputable<Boolean, IOException>() {
final Boolean validCredentials = accessToGithubWithModalProgress(project, settings.getHost(),
new ThrowableComputable<Boolean, IOException>() {
@Override
public Boolean compute() throws IOException {
ProgressManager.getInstance().getProgressIndicator().setText("Trying to login to GitHub");
@@ -291,7 +310,7 @@ public class GithubUtil {
}
// Otherwise our credentials are valid and they are successfully stored in settings
final String validPassword = settings.getPassword();
return accessToGithubWithModalProgress(project, new ThrowableComputable<RepositoryInfo, IOException>() {
return accessToGithubWithModalProgress(project, settings.getHost(), new ThrowableComputable<RepositoryInfo, IOException>() {
@Nullable
@Override
public RepositoryInfo compute() {