From 1f9da6f1a181c82f61634cf996479da7b198f16f Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 20 Feb 2013 20:26:24 +0400 Subject: [PATCH] [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). --- .../plugins/github/GithubShareAction.java | 2 +- .../plugins/github/GithubSslSupport.java | 38 +++++++++---------- .../jetbrains/plugins/github/GithubUtil.java | 37 +++++++++++++----- 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java index 6f5cdcba11c0..ca427dc9c642 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java @@ -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() { + GithubUtil.accessToGithubWithModalProgress(project, settings.getHost(), new ThrowableComputable() { @Override public Boolean compute() throws IOException { ProgressManager.getInstance().getProgressIndicator().setText("Trying to login to GitHub"); diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubSslSupport.java b/plugins/github/src/org/jetbrains/plugins/github/GithubSslSupport.java index a8c310c22963..0e95bdbe86cf 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubSslSupport.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubSslSupport.java @@ -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 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 choice = new Ref(-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; } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java index 54ad781e8b03..d5c548ff2d54 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java @@ -63,12 +63,29 @@ public class GithubUtil { return "https://" + GithubSettings.getInstance().getHost(); } - /** - * @deprecated TODO Use background progress - */ - @Deprecated - public static T accessToGithubWithModalProgress(@NotNull final Project project, + @Nullable + public static T accessToGithubWithModalProgress(@NotNull final Project project, @NotNull String host, @NotNull final ThrowableComputable 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 doAccessToGithubWithModalProgress(@NotNull final Project project, + @NotNull final ThrowableComputable computable) throws IOException { final Ref result = new Ref(); final Ref exception = new Ref(); 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 result = accessToGithubWithModalProgress(project, url, new ThrowableComputable() { @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, IOException>() { + return accessToGithubWithModalProgress(project, settings.getHost(), new ThrowableComputable, IOException>() { @Override public List 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() { + final Boolean validCredentials = accessToGithubWithModalProgress(project, settings.getHost(), + new ThrowableComputable() { @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() { + return accessToGithubWithModalProgress(project, settings.getHost(), new ThrowableComputable() { @Nullable @Override public RepositoryInfo compute() {