diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 46c91bc1cb70..778998263fb4 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -327,6 +327,29 @@ binding.setVariable("layoutMacApp", { String path, String ch, Map args -> String classPath = classPathLibs.collect {"\$APP_PACKAGE/lib/${it}" }.join(":") + String urlSchemes = "" + if (args.urlSchemes != null) { + urlSchemes += """ + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + Stacktrace + CFBundleURLSchemes + +""" + args.urlSchemes.each { scheme -> + urlSchemes += " ${scheme}" + } + urlSchemes += """ + + + +""" + } + ant.replace(file: "$path/Contents/Info.plist") { replacefilter(token: "@@build@@", value: args.buildNumber) replacefilter(token: "@@doc_types@@", value: ifNull(args.doc_types, "")) @@ -340,7 +363,7 @@ binding.setVariable("layoutMacApp", { String path, String ch, Map args -> replacefilter(token: "@@idea_properties@@", value: coreProperties) replacefilter(token: "@@class_path@@", value: classPath) replacefilter(token: "@@help_id@@", value: helpId) - replacefilter(token: "@@url_schemes@@", value: ifNull(args.urlSchemes, "")) + replacefilter(token: "@@url_schemes@@", value: urlSchemes) } if (executable != "idea") { diff --git a/platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java b/platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java index e2a99dc35ce1..d05c97458da1 100644 --- a/platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java @@ -16,26 +16,17 @@ package com.intellij.ui; import com.intellij.ide.CommandLineProcessor; -import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.util.io.URLUtil; import org.jetbrains.annotations.NotNull; -import java.io.UnsupportedEncodingException; import java.net.URI; -import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; /** * @author Dennis.Ushakov */ -public abstract class CustomProtocolHandler { - public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.customProtocolHandler"); - private final String myScheme; - - protected CustomProtocolHandler(String scheme) { - myScheme = scheme; - } - +public class CustomProtocolHandler { public boolean openLink(@NotNull URI uri) { final List args = getOpenArgs(uri); return !args.isEmpty() && CommandLineProcessor.processExternalCommandLine(args, null) != null; @@ -44,40 +35,30 @@ public abstract class CustomProtocolHandler { @NotNull public List getOpenArgs(URI uri) { final List args = new ArrayList(); - if (myScheme.equals(uri.getScheme())) { - final String query = uri.getQuery(); - String file = null; - String line = null; - if (query != null) { - for (String param : query.split("&")) { - String[] pair = param.split("="); - String key = decode(pair[0]); - if (pair.length > 1) { - if ("file".equals(key)) { - file = decode(pair[1]); - } else if ("line".equals(key)) { - line = decode(pair[1]); - } + final String query = uri.getQuery(); + String file = null; + String line = null; + if (query != null) { + for (String param : query.split("&")) { + String[] pair = param.split("="); + String key = URLUtil.unescapePercentSequences(pair[0]); + if (pair.length > 1) { + if ("file".equals(key)) { + file = URLUtil.unescapePercentSequences(pair[1]); + } else if ("line".equals(key)) { + line = URLUtil.unescapePercentSequences(pair[1]); } } } - if (file != null) { + } - if (line != null) { - args.add("--line"); - args.add(line); - } - args.add(file); + if (file != null) { + if (line != null) { + args.add("--line"); + args.add(line); } + args.add(file); } return args; } - - private static String decode(String s) { - try { - return URLDecoder.decode(s, "UTF-8"); - } catch (UnsupportedEncodingException e) { - return null; - } - } } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java index ae8e9bde3c05..444a778b4524 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java @@ -111,6 +111,7 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable { private static Runnable CURRENT_SETTER = null; private static Function CURRENT_GETTER = null; + private static CustomProtocolHandler ourProtocolHandler = null; private boolean myInFullScreen; private IdeFrameImpl myFrame; @@ -206,23 +207,22 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable { invoke(pool, "release"); } - // install uri handler - final ID mainBundle = invoke("NSBundle", "mainBundle"); - final ID urlTypes = invoke(mainBundle, "objectForInfoDictionaryKey:", Foundation.nsString("CFBundleURLTypes")); - if (urlTypes.equals(ID.NIL)) { - LOG.warn("no url bundle present"); - return; - } - Application.getApplication().setOpenURIHandler(new OpenURIHandler() { + if (ourProtocolHandler == null) { + // install uri handler + final ID mainBundle = invoke("NSBundle", "mainBundle"); + final ID urlTypes = invoke(mainBundle, "objectForInfoDictionaryKey:", Foundation.nsString("CFBundleURLTypes")); + if (urlTypes.equals(ID.NIL)) { + LOG.warn("no url bundle present"); + return; + } + ourProtocolHandler = new CustomProtocolHandler(); + Application.getApplication().setOpenURIHandler(new OpenURIHandler() { @Override public void openURI(AppEvent.OpenURIEvent event) { - for (CustomProtocolHandler handler : CustomProtocolHandler.EP_NAME.getExtensions()) { - if (handler.openLink(event.getURI())) { - return; - } - } + ourProtocolHandler.openLink(event.getURI()); } }); + } } public void remove() { diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index e9e81089324b..d23e7fe23f10 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -167,7 +167,6 @@ - diff --git a/platform/platform-tests/testSrc/com/intellij/ui/CustomProtocolHandlerTest.java b/platform/platform-tests/testSrc/com/intellij/ui/CustomProtocolHandlerTest.java new file mode 100644 index 000000000000..2df1d0a48f2b --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/ui/CustomProtocolHandlerTest.java @@ -0,0 +1,21 @@ +package com.intellij.ui; + +import junit.framework.TestCase; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +/** + * @author Dennis.Ushakov + */ +public class CustomProtocolHandlerTest extends TestCase { + public void testOpenOurLink() throws URISyntaxException, MalformedURLException { + final URI uri = new URI("x-mine://open?file=/Users/denofevil/RubymineProjects/JRubyRails/app/assets/javascripts/application.js.coffee&line=2"); + final List args = new CustomProtocolHandler().getOpenArgs(uri); + assertTrue(args.contains("--line")); + assertTrue(args.contains("2")); + assertTrue(args.contains("/Users/denofevil/RubymineProjects/JRubyRails/app/assets/javascripts/application.js.coffee")); + } +}