From c0e450476ae748a10dfd81a468e7f5c8f29dd1a2 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 18 Aug 2025 11:38:08 -0400 Subject: [PATCH] GP-0: The Visual Studio Code Integration options can now accept 2 optional arguments, allowing a Flatpak installation of VSCode to be launched by Ghidra (Closes #8442) --- .../VSCodeIntegration/VSCodeIntegration.htm | 16 ++++++++++++++++ .../vscode/VSCodeIntegrationOptionsPlugin.java | 18 +++++++++++++++++- .../core/vscode/VSCodeIntegrationPlugin.java | 11 +++++++++++ .../plugin/core/vscode/VSCodeLauncherTask.java | 2 ++ .../app/services/VSCodeIntegrationService.java | 6 ++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/help/help/topics/VSCodeIntegration/VSCodeIntegration.htm b/Ghidra/Features/Base/src/main/help/help/topics/VSCodeIntegration/VSCodeIntegration.htm index 5e4b05751b..e525ed6f2a 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/VSCodeIntegration/VSCodeIntegration.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/VSCodeIntegration/VSCodeIntegration.htm @@ -37,10 +37,26 @@ Path to a Visual Studio Code executable file. It defaults to the most commonly used location on your specific platform. + + Visual Studio Code Argument 1 (optional) + An optional argument to pass to the Visual Studio Code + executable. + + + Visual Studio Code Argument 2 (optional) + An optional argument to pass to the Visual Studio Code + executable. + +

+ One use of the optional argument fields is to + launch a Flatpak installation of Visual Studio Code. In this case, the executable path might be + "/usr/bin/flatpak", and the two optional arguments might be "run" and "com.visualstudio.code". +

+

Create Visual Studio Code Module Project

This action creates a new Visual Studio Code project folder which can be used as a convenient starting point to develop a new Ghidra module. The new project will be linked against the diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeIntegrationOptionsPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeIntegrationOptionsPlugin.java index e32e0675a0..1739bb634b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeIntegrationOptionsPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeIntegrationOptionsPlugin.java @@ -44,9 +44,21 @@ public class VSCodeIntegrationOptionsPlugin extends Plugin implements Applicatio public static final String PLUGIN_OPTIONS_NAME = "Visual Studio Code Integration"; public static final String VSCODE_EXE_PATH_OPTION = "Visual Studio Code Executable Path"; - private static final String VSCODE_EXE_PATH_DESC = "Path to Visual Studio Code executable"; + private static final String VSCODE_EXE_PATH_DESC = "Full path to Visual Studio Code executable"; private static final File VSCODE_EXE_PATH_DEFAULT = getDefaultVSCodeExecutable(); + public static final String VSCODE_ARG1_OPTION = + "Visual Studio Code Launch Argument 1 (optional)"; + private static final String VSCODE_ARG1_DESC = + "Optional argument 1 for Visual Studio Code executable"; + private static final String VSCODE_ARG1_DEFAULT = null; + + public static final String VSCODE_ARG2_OPTION = + "Visual Studio Code Launch Argument 2 (optional)"; + private static final String VSCODE_ARG2_DESC = + "Optional argument 2 for Visual Studio Code executable"; + private static final String VSCODE_ARG2_DEFAULT = null; + public VSCodeIntegrationOptionsPlugin(PluginTool tool) { super(tool); } @@ -57,6 +69,10 @@ public class VSCodeIntegrationOptionsPlugin extends Plugin implements Applicatio ToolOptions options = tool.getOptions(PLUGIN_OPTIONS_NAME); options.registerOption(VSCODE_EXE_PATH_OPTION, OptionType.FILE_TYPE, VSCODE_EXE_PATH_DEFAULT, null, VSCODE_EXE_PATH_DESC); + options.registerOption(VSCODE_ARG1_OPTION, OptionType.STRING_TYPE, + VSCODE_ARG1_DEFAULT, null, VSCODE_ARG1_DESC); + options.registerOption(VSCODE_ARG2_OPTION, OptionType.STRING_TYPE, + VSCODE_ARG2_DEFAULT, null, VSCODE_ARG2_DESC); options.setOptionsHelpLocation( new HelpLocation("VSCodeIntegration", "VSCodeIntegrationOptions")); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeIntegrationPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeIntegrationPlugin.java index 4c7e20a2f8..1929f31da3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeIntegrationPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeIntegrationPlugin.java @@ -19,6 +19,7 @@ import java.io.*; import java.nio.charset.StandardCharsets; import java.util.*; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.*; import com.google.gson.*; @@ -153,6 +154,16 @@ public class VSCodeIntegrationPlugin extends ProgramPlugin implements VSCodeInte return vscodeExecutableFile; } + @Override + public List getVSCodeArguments() { + List args = new ArrayList<>(); + CollectionUtils.addIgnoreNull(args, + options.getString(VSCodeIntegrationOptionsPlugin.VSCODE_ARG1_OPTION, null)); + CollectionUtils.addIgnoreNull(args, + options.getString(VSCodeIntegrationOptionsPlugin.VSCODE_ARG2_OPTION, null)); + return args; + } + @Override public void launchVSCode(File file) { TaskLauncher.launch(new VSCodeLauncherTask(this, file)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeLauncherTask.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeLauncherTask.java index 9f75f89b72..1382caf21f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeLauncherTask.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/vscode/VSCodeLauncherTask.java @@ -59,6 +59,7 @@ class VSCodeLauncherTask extends Task { // location present the user with the options window, and when they close that window, try // again. File vscodeExecutableFile; + List vscodeArgs = vscodeService.getVSCodeArguments(); try { vscodeExecutableFile = vscodeService.getVSCodeExecutableFile(); } @@ -93,6 +94,7 @@ class VSCodeLauncherTask extends Task { try { List args = new ArrayList<>(); args.add(vscodeExecutableFile.getAbsolutePath()); + args.addAll(vscodeArgs); args.add("-a"); args.add(workspaceFile.getAbsolutePath()); args.add(file.getAbsolutePath()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/services/VSCodeIntegrationService.java b/Ghidra/Features/Base/src/main/java/ghidra/app/services/VSCodeIntegrationService.java index 96dd6ef274..98ec51731e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/services/VSCodeIntegrationService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/services/VSCodeIntegrationService.java @@ -16,6 +16,7 @@ package ghidra.app.services; import java.io.*; +import java.util.List; import ghidra.framework.options.ToolOptions; @@ -36,6 +37,11 @@ public interface VSCodeIntegrationService { */ public File getVSCodeExecutableFile() throws FileNotFoundException; + /** + * {@return the Visual Studio Code executable arguments} + */ + public List getVSCodeArguments(); + /** * Launches Visual Studio Code *