From d377b9642bd525d293f8d6b0a3381249168b33cb Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Wed, 7 Dec 2022 17:09:00 -0500 Subject: [PATCH] GP-2897 Allow Diff with another open program within same tool. Modified OpenVersionedFileDialog to faciltate the program selection. --- .../core/datamgr/DataTypeManagerPlugin.java | 6 +- .../core/progmgr/ProgramManagerPlugin.java | 6 +- .../main/OpenVersionedFileDialog.java | 260 +++++++++++++++--- .../ProgramDiff/certification.manifest | 2 +- .../src/main/help/help/topics/Diff/Diff.htm | 35 ++- .../topics/Diff/images/SelectOpenProgram.png | Bin 0 -> 13941 bytes .../topics/Diff/images/SelectOtherProgram.png | Bin 16218 -> 19402 bytes .../images/SelectOtherVersionedProgram.png | Bin 32691 -> 33379 bytes .../plugin/core/diff/DiffActionManager.java | 198 ++++++------- .../plugin/core/diff/ProgramDiffPlugin.java | 198 +++++++------ .../java/ghidra/app/services/DiffService.java | 18 +- .../core/diff/DiffSaveSettingsTest.java | 4 +- .../ghidra/app/plugin/core/diff/DiffTest.java | 8 +- .../app/plugin/core/diff/DiffTestAdapter.java | 18 +- .../ghidra/framework/data/LinkHandler.java | 4 +- .../framework/project/DefaultProject.java | 6 +- .../java/help/screenshot/DiffScreenShots.java | 54 ++-- 17 files changed, 536 insertions(+), 281 deletions(-) create mode 100644 Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/images/SelectOpenProgram.png diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java index 9d13288744..f2727b03f8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java @@ -95,7 +95,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin private DataTypeManagerHandler dataTypeManagerHandler; private DataTypesProvider provider; - private OpenVersionedFileDialog openDialog; + private OpenVersionedFileDialog openDialog; private Map recentlyOpenedArchiveMap; private Map installArchiveMap; @@ -587,8 +587,8 @@ public class DataTypeManagerPlugin extends ProgramPlugin } }; openDialog = - new OpenVersionedFileDialog(tool, "Open Project Data Type Archive", - df -> DataTypeArchive.class.isAssignableFrom(df.getDomainObjectClass())); + new OpenVersionedFileDialog<>(tool, "Open Project Data Type Archive", + DataTypeArchive.class); openDialog.setHelpLocation(new HelpLocation(HelpTopics.PROGRAM, "Open_File_Dialog")); openDialog.addOkActionListener(listener); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java index 454ecd2fd9..d69dd31b39 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java @@ -83,7 +83,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { private MultiProgramManager programMgr; private ProgramSaveManager programSaveMgr; private int transactionID = -1; - private OpenVersionedFileDialog openDialog; + private OpenVersionedFileDialog openDialog; private boolean locked = false; private UndoAction undoAction; private RedoAction redoAction; @@ -617,9 +617,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { doOpenProgram(domainFile, version, OPEN_CURRENT); } }; - openDialog = new OpenVersionedFileDialog(tool, "Open Program", f -> { - return Program.class.isAssignableFrom(f.getDomainObjectClass()); - }); + openDialog = new OpenVersionedFileDialog<>(tool, "Open Program", Program.class); openDialog.setHelpLocation(new HelpLocation(HelpTopics.PROGRAM, "Open_File_Dialog")); openDialog.addOkActionListener(listener); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java index 02c66284a2..0aa646b764 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java @@ -15,10 +15,10 @@ */ package ghidra.framework.main; -import java.awt.BorderLayout; -import java.awt.Dimension; +import java.awt.*; import java.awt.event.MouseEvent; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -26,6 +26,8 @@ import javax.swing.*; import docking.ActionContext; import docking.action.DockingActionIf; +import docking.event.mouse.GMouseListenerAdapter; +import docking.widgets.table.*; import ghidra.framework.main.datatree.VersionHistoryPanel; import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginTool; @@ -35,10 +37,9 @@ import ghidra.util.Msg; /** * Dialog to open a file that is versioned and allow a version to be * opened. - * - * + * @param domain object class */ -public class OpenVersionedFileDialog extends DataTreeDialog { +public class OpenVersionedFileDialog extends DataTreeDialog { private static final String SHOW_HISTORY_PREFERENCES_KEY = "OPEN_PROGRAM_DIALOG.SHOW_HISTORY"; private static final String HEIGHT_PREFERENCES_KEY = "OPEN_PROGRAM_DIALOG.HEIGHT"; private static final String WIDTH_NO_HISTORY_PREFERENCES_KEY = @@ -50,6 +51,10 @@ public class OpenVersionedFileDialog extends DataTreeDialog { private final static int DEFAULT_WIDTH_WITH_HISTORY = 800; private final static int DIVIDER_SIZE = 2; + private final static int PROJECT_FILES_TAB = 0; + private final static int OPEN_OBJECT_LIST_TAB = 1; + + private JTabbedPane tabbedPane; // null if openDomainObjects not specified private JSplitPane splitPane; private JButton historyButton; private JPanel mainPanel; @@ -59,30 +64,71 @@ public class OpenVersionedFileDialog extends DataTreeDialog { private VersionHistoryPanel historyPanel; private List popupActions = Collections.emptyList(); + private Class domainObjectClass; + private List openDomainObjects; // list of allowed domain object which are already open + private GFilterTable openObjectsTable; + /** * Constructor * @param tool tool where the file is being opened. * @param title title to use - * @param filter filter used to control what is displayed in data tree. + * @param domainObjectClass allowed domain object class which corresponds to {@code } */ - public OpenVersionedFileDialog(PluginTool tool, String title, DomainFileFilter filter) { - super(tool.getToolFrame(), title, DataTreeDialog.OPEN, filter); + public OpenVersionedFileDialog(PluginTool tool, String title, Class domainObjectClass) { + super(tool.getToolFrame(), title, DataTreeDialog.OPEN, f -> { + return domainObjectClass.isAssignableFrom(f.getDomainObjectClass()); + }); this.tool = tool; + this.domainObjectClass = domainObjectClass; init(); } /** - * Get the domain object for the selected version. - * @param consumer consumer - * @param readOnly true if the domain object should be opened read only, - * versus immutable - * @return null if a versioned file was not selected + * Set an optional list of already open domain objects of type {@code } which may be + * selected instead of a project domain file. The {@link #getDomainObject(Object, boolean)} + * method should be used when this optional list has been set. If this dialog is reused + * the list should be set null if previously set. This method must be invoked prior to + * showing the dialog. + * @param openDomainObjects list of open domain objects from which a selection may be made. */ - public DomainObject getVersionedDomainObject(Object consumer, boolean readOnly) { - if (historyPanel != null) { - return historyPanel.getSelectedVersion(consumer, readOnly); + public void setOpenObjectChoices(List openDomainObjects) { + this.openDomainObjects = (openDomainObjects != null && !openDomainObjects.isEmpty()) + ? new ArrayList<>(openDomainObjects) + : null; + } + + /** + * Get the selected domain object for read-only or immutable use. + * If an existing open object is selected its original mode applies but consumer will + * be added. + * @param consumer consumer + * @param readOnly true if the domain object should be opened read only, versus immutable + * @return null if a file was not selected + */ + @SuppressWarnings("unchecked") // relies on content class filter + public T getDomainObject(Object consumer, boolean readOnly) { + T dobj = null; + if (usingOpenProgramList()) { + dobj = getSelectedOpenDomainObject(); + if (dobj != null) { + dobj.addConsumer(consumer); + } + return dobj; } - return null; + if (historyPanel != null) { + dobj = (T) historyPanel.getSelectedVersion(consumer, readOnly); + } + if (dobj == null) { + DomainFile domainFile = getDomainFile(); + if (domainFile != null) { + GetVersionedObjectTask task = + new GetVersionedObjectTask(consumer, domainFile, DomainFile.DEFAULT_VERSION, + readOnly); + tool.execute(task, 1000); + return (T) task.getVersionedObject(); + } + } + return dobj; } /** @@ -90,18 +136,36 @@ public class OpenVersionedFileDialog extends DataTreeDialog { * @return -1 if a version history was not selected */ public int getVersion() { - if (historyPanel != null) { + if (historyPanel != null && !usingOpenProgramList()) { return historyPanel.getSelectedVersionNumber(); } return -1; } - /* (non-Javadoc) - * @see ghidra.framework.main.DataTreeDialog#buildMainPanel() - */ + @Override + public DomainFile getDomainFile() { + if (usingOpenProgramList()) { + return null; + } + return super.getDomainFile(); + } + + @Override + public DomainFolder getDomainFolder() { + if (usingOpenProgramList()) { + return null; + } + return super.getDomainFolder(); + } + @Override protected JPanel buildMainPanel() { - mainPanel = super.buildMainPanel(); + + mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(super.buildMainPanel(), BorderLayout.CENTER); + JPanel historyButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + historyButtonPanel.add(historyButton); + mainPanel.add(historyButtonPanel, BorderLayout.SOUTH); mainPanel.setMinimumSize(new Dimension(200, HEIGHT)); splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); @@ -112,8 +176,8 @@ public class OpenVersionedFileDialog extends DataTreeDialog { splitPane.setDividerLocation(1.0); splitPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); - JPanel outerPanel = new JPanel(new BorderLayout()); - outerPanel.add(splitPane); + JPanel projectFilePanel = new JPanel(new BorderLayout()); + projectFilePanel.add(splitPane); String showHistory = Preferences.getProperty(SHOW_HISTORY_PREFERENCES_KEY, Boolean.FALSE.toString(), true); @@ -122,26 +186,91 @@ public class OpenVersionedFileDialog extends DataTreeDialog { showHistoryPanel(true); } - return outerPanel; + openObjectsTable = null; + tabbedPane = null; + + updateOkTooltip(); + + if (openDomainObjects == null) { + return projectFilePanel; // return Project File selection panel only + } + + // Create tabbed pane with "Project Files" and "Open Program" tabs + // NOTE: actual tab name reflects domainObjectClass name + tabbedPane = new JTabbedPane(); + tabbedPane.setName("Tabs"); + tabbedPane.add("Project Files", projectFilePanel); + tabbedPane.add("Open " + domainObjectClass.getSimpleName() + "s", + buildOpenObjectsTable()); + + tabbedPane.addChangeListener(e -> { + int selectedTabIndex = tabbedPane.getModel().getSelectedIndex(); + if (selectedTabIndex == PROJECT_FILES_TAB) { + // Project tree and History use + String nameText = getNameText(); + setOkEnabled((nameText != null) && !nameText.isEmpty()); + } + else { // OPEN_OBJECT_LIST_TAB + setOkEnabled(getSelectedOpenDomainObject() != null); + } + updateOkTooltip(); + }); + + JPanel tabbedPanel = new JPanel(); + tabbedPanel.setLayout(new BorderLayout()); + tabbedPanel.add(tabbedPane, BorderLayout.CENTER); + + tabbedPane.setSelectedIndex(PROJECT_FILES_TAB); + return tabbedPanel; } - private void advancedButtonCallback() { - showHistoryPanel(!historyIsShowing); + private boolean usingOpenProgramList() { + return tabbedPane != null && + tabbedPane.getModel().getSelectedIndex() == OPEN_OBJECT_LIST_TAB; + } + private T getSelectedOpenDomainObject() { + if (!usingOpenProgramList()) { + return null; + } + return openObjectsTable.getSelectedRowObject(); + } + + private Component buildOpenObjectsTable() { + + openObjectsTable = new GFilterTable<>(new OpenObjectsTableModel()); + GTable table = openObjectsTable.getTable(); + table.getSelectionModel() + .setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + openObjectsTable.addSelectionListener(e -> { + setOkEnabled(true); + okButton.setToolTipText("Use the selected " + domainObjectClass.getSimpleName()); + }); + + table.addMouseListener(new GMouseListenerAdapter() { + @Override + public void doubleClickTriggered(MouseEvent e) { + if (okButton.isEnabled()) { + okCallback(); + } + } + }); + + return openObjectsTable; } private void showHistoryPanel(boolean showHistory) { historyIsShowing = showHistory; if (showHistory) { createHistoryPanel(); - historyButton.setText("No History"); + historyButton.setText("Hide History"); DomainFile df = treePanel.getSelectedDomainFile(); historyPanel.setDomainFile(df); splitPane.setDividerSize(DIVIDER_SIZE); splitPane.setDividerLocation(DEFAULT_WIDTH_NO_HISTORY - 4); } else { - historyButton.setText("History>>"); + historyButton.setText("Show History>>"); splitPane.setDividerSize(0); splitPane.setRightComponent(null); historyPanel = null; @@ -175,7 +304,6 @@ public class OpenVersionedFileDialog extends DataTreeDialog { Preferences.setProperty(SHOW_HISTORY_PREFERENCES_KEY, Boolean.toString(historyIsShowing)); Preferences.store(); - } @Override @@ -203,6 +331,25 @@ public class OpenVersionedFileDialog extends DataTreeDialog { } } + private void updateOkTooltip() { + String tip; + if (usingOpenProgramList()) { + tip = "Use selected " + domainObjectClass.getSimpleName(); + } + else { + tip = "Open the selected file"; + if (historyPanel != null && historyIsShowing) { + int versionNumber = historyPanel.getSelectedVersionNumber(); + if (versionNumber >= 0) { + DomainFile df = OpenVersionedFileDialog.super.getDomainFile(); + okButton.setToolTipText( + "Open version " + versionNumber + " for " + df.getName()); + } + } + } + okButton.setToolTipText(tip); + } + private boolean createHistoryPanel() { try { historyPanel = new VersionHistoryPanel(tool, null); @@ -220,24 +367,16 @@ public class OpenVersionedFileDialog extends DataTreeDialog { if (e.getValueIsAdjusting()) { return; } - okButton.setToolTipText("Open the selected file"); - int versionNumber = historyPanel.getSelectedVersionNumber(); - if (versionNumber >= 0) { - DomainFile df = OpenVersionedFileDialog.super.getDomainFile(); - okButton.setToolTipText("Open version " + versionNumber + " for " + df.getName()); - } + updateOkTooltip(); }); return true; } private void init() { historyButton = new JButton("History>>"); - historyButton.addActionListener(e -> advancedButtonCallback()); - addButton(historyButton); + historyButton.addActionListener(e -> showHistoryPanel(!historyIsShowing)); - okButton.setToolTipText("Open the selected file"); rootPanel.setPreferredSize(getPreferredSizeForHistoryState()); - } @Override @@ -249,6 +388,7 @@ public class OpenVersionedFileDialog extends DataTreeDialog { DomainFile df = treePanel.getSelectedDomainFile(); historyPanel.setDomainFile(df); } + updateOkTooltip(); }); } @@ -264,4 +404,44 @@ public class OpenVersionedFileDialog extends DataTreeDialog { return actionContext; } + + private class OpenObjectsTableModel extends AbstractGTableModel { + + @Override + public String getName() { + return "Open DomainObject List"; + } + + @Override + public List getModelData() { + return openDomainObjects; + } + + @Override + public Object getColumnValueForRow(T t, int columnIndex) { + // only one column + return t.getDomainFile().toString(); + } + + @Override + public int getColumnCount() { + return 1; + } + + @Override + public String getColumnName(int columnIndex) { + return "Program Path"; + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + + } } diff --git a/Ghidra/Features/ProgramDiff/certification.manifest b/Ghidra/Features/ProgramDiff/certification.manifest index cc80bd6c37..d351c3e3bd 100644 --- a/Ghidra/Features/ProgramDiff/certification.manifest +++ b/Ghidra/Features/ProgramDiff/certification.manifest @@ -26,6 +26,7 @@ src/main/help/help/topics/Diff/images/DiffApplySettings.png||GHIDRA||||END| src/main/help/help/topics/Diff/images/DiffApplySettingsPopup.png||GHIDRA||reviewed||END| src/main/help/help/topics/Diff/images/DiffDetails.png||GHIDRA||||END| src/main/help/help/topics/Diff/images/DiffSelect16.png||GHIDRA||reviewed||END| +src/main/help/help/topics/Diff/images/SelectOpenProgram.png||GHIDRA||||END| src/main/help/help/topics/Diff/images/SelectOtherProgram.png||GHIDRA||||END| src/main/help/help/topics/Diff/images/SelectOtherVersionedProgram.png||GHIDRA||||END| src/main/help/help/topics/Diff/images/disk.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| @@ -44,5 +45,4 @@ src/main/resources/images/eraser_arrow16.png||GHIDRA||||END| src/main/resources/images/pencil16.png||GHIDRA||reviewed||END| src/main/resources/images/pencil_arrow16.png||GHIDRA||reviewed||END| src/main/resources/images/settings16.gif||GHIDRA||reviewed||END| -src/main/resources/images/table_relationship.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/xmag.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| diff --git a/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/Diff.htm b/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/Diff.htm index b84a675cdb..69db26583d 100644 --- a/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/Diff.htm +++ b/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/Diff.htm @@ -21,14 +21,14 @@ program in order to get another user's changes into your program.

- - Opening and Closing the Second Program + + Opening and Closing the Diff View

The Open/Close Diff View icon in the Code Browser tool bar is used for both opening and closing - the second program in the Code Browser. This is one of two ways to open the Diff + a second program in the Code Browser Diff panel. This is one of two ways to open the Diff tool. The other is the menu action, Tools -> @@ -70,9 +70,9 @@ -> Program Differences... . This is one of two ways to open the Diff - tool. The other is the Open/Close Program Diff icon + tool. The other is the Open/Close Diff View icon - in the Code Browser tool bar which is described above in Open/Close Diff View. + in the Code Browser tool bar which is described above in Opening and Closing the Diff View. The following describes using the menu action to open the Diff tool.

With a program open in the Code Browser tool, do the following to @@ -100,14 +100,27 @@ defined. In other words, they should be the same type of program (i.e. based on the same program language).
- If you wish to Diff against a previous version of a - versioned program, select the History>> - button of a program. Select the versioned program from the tree. - Next select the desired version of the program from the history - list on the right side of the dialog.
+ If you wish to Diff against a specific version of a + versioned program, a specific version may be seleected from the + Version History table. The project file history panel is displayed + when the History>> button is clicked. + Select the versioned program from the tree. + Next select the desired version of the program from the Version History + table on the right side of the dialog.


+ + + If you wish to Diff against another program which is already open in the same tool + you can select a compatible program from the Open Programs tab. Programs + which are not compatible (e.g., different architecture) are not shown in the table. + The Open Programs tab is not available if compatible open programs are not + found. You may return to the project file tree selection panel by clicking the + Project Files tab. +
+
+
  • Click the OK button.
  • The Determine Program Differences dialog is displayed. @@ -269,7 +282,7 @@ - + diff --git a/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/images/SelectOpenProgram.png b/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/images/SelectOpenProgram.png new file mode 100644 index 0000000000000000000000000000000000000000..239796f283536edf70080a858c8ecc76488d73df GIT binary patch literal 13941 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 literal 0 HcmV?d00001 diff --git a/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/images/SelectOtherProgram.png b/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/images/SelectOtherProgram.png index 201c7847e5e836bb77a39f3b4669c872de24107b..99b79cb0d3bf373e937a5b129d4d7f581b7aee9d 100644 GIT binary patch literal 19402 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 diff --git a/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/images/SelectOtherVersionedProgram.png b/Ghidra/Features/ProgramDiff/src/main/help/help/topics/Diff/images/SelectOtherVersionedProgram.png index dc6412956e7ed21d878f8d7e5be96c7e5cc93868..825f2a340ff1816f9ca3fb093697779b348165fd 100644 GIT binary patch literal 33379 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 B=av8f literal 32691 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 PE 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 C8|HBU diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffActionManager.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffActionManager.java index 3d96eb7732..871d870f42 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffActionManager.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffActionManager.java @@ -56,7 +56,7 @@ class DiffActionManager { static final String GET_DIFFS_ACTION = "Get Differences"; static final String SELECT_ALL_DIFFS_ACTION = "Select All Differences"; static final String P1_SELECT_TO_P2_ACTION = "Set Program1 Selection On Program2"; - static final String OPEN_CLOSE_PROGRAM2_ACTION = "Open/Close Program View"; + static final String OPEN_CLOSE_DIFF_VIEW_ACTION = "Open/Close Diff View"; static final String VIEW_PROGRAM_DIFF_ACTION = "View Program Differences"; private DockingAction applyDiffsAction; @@ -69,11 +69,12 @@ class DiffActionManager { private DockingAction getDiffsAction; private DockingAction selectAllDiffsAction; private DockingAction p1SelectToP2Action; - private ToggleDockingAction openCloseProgram2Action; + private OpenCloseDiffViewAction openCloseDiffViewAction; private DockingAction viewProgramDiffAction; /** * Creates an action manager for the Program Diff plugin. + * @param plugin Diff plugin */ public DiffActionManager(ProgramDiffPlugin plugin) { this.plugin = plugin; @@ -86,7 +87,7 @@ class DiffActionManager { */ void setCodeViewerService(CodeViewerService codeViewerService) { this.codeViewerService = codeViewerService; - codeViewerService.addLocalAction(openCloseProgram2Action); + codeViewerService.addLocalAction(openCloseDiffViewAction); } /** @@ -127,7 +128,7 @@ class DiffActionManager { */ void programClosed(Program program) { boolean hasProgram = (plugin.getCurrentProgram() != null); - openCloseProgram2Action.setEnabled(hasProgram && !plugin.isTaskInProgress()); + openCloseDiffViewAction.setEnabled(hasProgram && !plugin.isTaskInProgress()); } /** @@ -136,26 +137,27 @@ class DiffActionManager { * @param program the newly active program */ void setActiveProgram(Program program) { + viewProgramDiffAction.setEnabled(program != null); boolean enabled = program != null && !plugin.isTaskInProgress(); - openCloseProgram2Action.setEnabled(enabled); + openCloseDiffViewAction.setEnabled(enabled); if (enabled) { - if (openCloseProgram2Action.isSelected()) { + if (openCloseDiffViewAction.isSelected()) { // we are diffing--is the current program the diff program? Program firstProgram = plugin.getFirstProgram(); if (firstProgram == program) { - openCloseProgram2Action.setDescription("Close Diff View"); + openCloseDiffViewAction.setDescription("Close Diff View"); } else { - openCloseProgram2Action.setDescription("Bring Diff View to Front"); + openCloseDiffViewAction.setDescription("Bring Diff View to Front"); } } } else { // no active diff - openCloseProgram2Action.setDescription("Open Diff View"); + openCloseDiffViewAction.setDescription("Open Diff View"); } } @@ -164,16 +166,16 @@ class DiffActionManager { * second program to the program Diff. Actions are adjusted accordingly. */ void secondProgramOpened() { - openCloseProgram2Action.setSelected(true); - openCloseProgram2Action.setDescription("Close Diff View"); + openCloseDiffViewAction.setSelected(true); + openCloseDiffViewAction.setDescription("Close Diff View"); Program firstProgram = plugin.getFirstProgram(); Program secondProgram = plugin.getSecondProgram(); - String firstName = firstProgram.getName(); - String secondName = secondProgram.getName(); + String firstName = firstProgram.getDomainFile().getName(); + String secondName = secondProgram.getDomainFile().getName(); //@formatter:off - openCloseProgram2Action.setDescription( + openCloseDiffViewAction.setDescription( "

    Close Diff View

    " + "Current diff: " + ""+HTMLUtilities.escapeHTML(firstName)+" to " +HTMLUtilities.escapeHTML(secondName)+""); @@ -185,8 +187,8 @@ class DiffActionManager { * program Diff was closed. Actions are adjusted accordingly. */ void secondProgramClosed() { - openCloseProgram2Action.setSelected(false); - openCloseProgram2Action.setDescription("Open Diff View"); + openCloseDiffViewAction.setSelected(false); + openCloseDiffViewAction.setDescription("Open Diff View"); showDiffSettingsAction.setEnabled(false); diffDetailsAction.setEnabled(false); removeActions(); @@ -197,7 +199,7 @@ class DiffActionManager { } void setOpenCloseActionSelected(boolean selected) { - openCloseProgram2Action.setSelected(selected); + openCloseDiffViewAction.setSelected(selected); } void updateActions(boolean taskInProgress, boolean inDiff, boolean hasSelectionInView, @@ -217,32 +219,34 @@ class DiffActionManager { Program currentProgram = plugin.getCurrentProgram(); boolean hasProgram = (currentProgram != null); - openCloseProgram2Action.setEnabled(hasProgram && !taskInProgress); + openCloseDiffViewAction.setEnabled(hasProgram && !taskInProgress); } /** * Removes all the actions. */ void dispose() { - codeViewerService.removeLocalAction(openCloseProgram2Action); + codeViewerService.removeLocalAction(openCloseDiffViewAction); plugin.getTool().removeAction(viewProgramDiffAction); removeActions(); } private void createActions() { - viewProgramDiffAction = new DockingAction(VIEW_PROGRAM_DIFF_ACTION, plugin.getName()) { - @Override - public void actionPerformed(ActionContext context) { - plugin.selectProgram2(); - } - }; - String[] menuPath = { ToolConstants.MENU_TOOLS, "Program &Differences..." }; + viewProgramDiffAction = + new DockingAction(VIEW_PROGRAM_DIFF_ACTION, plugin.getName()) { + @Override + public void actionPerformed(ActionContext context) { + plugin.selectProgram2(); + } + }; viewProgramDiffAction.setEnabled(plugin.getCurrentProgram() != null); - viewProgramDiffAction.setMenuBarData(new MenuData(menuPath, "View")); + viewProgramDiffAction.setMenuBarData(new MenuData( + new String[] { ToolConstants.MENU_TOOLS, VIEW_PROGRAM_DIFF_ACTION + "..." }, + "ProgramDiff")); viewProgramDiffAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_2, 0)); - viewProgramDiffAction.setHelpLocation( - new HelpLocation(HelpTopics.DIFF, "Program_Differences")); + viewProgramDiffAction + .setHelpLocation(new HelpLocation(HelpTopics.DIFF, "Program_Differences")); plugin.getTool().addAction(viewProgramDiffAction); applyDiffsAction = new DiffAction(APPLY_DIFFS_ACTION) { @@ -377,72 +381,7 @@ class DiffActionManager { "Select Program 2 highlights using selection in Program 1."); p1SelectToP2Action.setToolBarData(new ToolBarData(icon, SELECT_GROUP)); - openCloseProgram2Action = - new ToggleDockingAction(OPEN_CLOSE_PROGRAM2_ACTION, plugin.getName()) { - @Override - public void actionPerformed(ActionContext context) { - // - // No active diff--start one. - // - if (openCloseProgram2Action.isSelected()) { - plugin.selectProgram2(); - return; - } - - // - // We have a diff session--is the current program the one for the diff session? - // If not, simply make the diff program the active program (this is useful for - // users when they were diffing, but then opened a different program). - // - if (activateDiffProgram()) { - // clicking the action will change the selected state--keep it selected - setSelected(true); - setDescription("Close Diff View"); - return; - } - - // - // Otherwise, close the diff. - // - closeDiff(); - } - - private void closeDiff() { - int choice = OptionDialog.showYesNoCancelDialog(null, "Close Diff Session", - "Close the current diff session?"); - if (choice == OptionDialog.YES_OPTION) { - plugin.closeProgram2(); - setDescription("Open Diff View"); - } - else { - // clicking the action will change the selected state--keep it selected - setSelected(true); - setDescription("Close Diff View"); - } - } - - private boolean activateDiffProgram() { - - Program currentProgram = plugin.getCurrentProgram(); - Program firstProgram = plugin.getFirstProgram(); - boolean isFirstProgram = (firstProgram == currentProgram); - if (isFirstProgram) { - return false; // already active--nothing to do! - } - - plugin.activeProgram(firstProgram); - return true; - } - }; - icon = new GIcon("icon.plugin.programdiff.open.close.program"); - openCloseProgram2Action.setEnabled(false); - openCloseProgram2Action.setKeyBindingData( - new KeyBindingData('C', InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK)); - openCloseProgram2Action.setToolBarData(new ToolBarData(icon, "zzz")); - openCloseProgram2Action.setHelpLocation( - new HelpLocation(HelpTopics.DIFF, OPEN_CLOSE_PROGRAM2_ACTION)); - openCloseProgram2Action.setSelected(false); - openCloseProgram2Action.setDescription("Open Diff View"); + openCloseDiffViewAction = new OpenCloseDiffViewAction(); } private abstract class DiffAction extends DockingAction { @@ -457,4 +396,73 @@ class DiffActionManager { return (context instanceof OtherPanelContext); } } + + private class OpenCloseDiffViewAction extends ToggleDockingAction { + + OpenCloseDiffViewAction() { + super(OPEN_CLOSE_DIFF_VIEW_ACTION, plugin.getName()); + GIcon icon = new GIcon("icon.plugin.programdiff.open.close.program"); + setEnabled(false); + setToolBarData(new ToolBarData(icon, "zzz")); + setHelpLocation( + new HelpLocation(HelpTopics.DIFF, OPEN_CLOSE_DIFF_VIEW_ACTION)); + setSelected(false); + setDescription("Open Diff View"); + } + + @Override + public void actionPerformed(ActionContext context) { + // + // No active diff--start one. + // + if (openCloseDiffViewAction.isSelected()) { + plugin.selectProgram2(); + return; + } + + // + // We have a diff session--is the current program the one for the diff session? + // If not, simply make the diff program the active program (this is useful for + // users when they were diffing, but then opened a different program). + // + if (activateDiffProgram()) { + // clicking the action will change the selected state--keep it selected + setSelected(true); + setDescription("Close Diff View"); + return; + } + + // + // Otherwise, close the diff. + // + closeDiff(); + } + + private void closeDiff() { + int choice = OptionDialog.showYesNoCancelDialog(null, "Close Diff Session", + "Close the current diff session?"); + if (choice == OptionDialog.YES_OPTION) { + plugin.closeProgram2(); + setDescription("Open Diff View"); + } + else { + // clicking the action will change the selected state--keep it selected + setSelected(true); + setDescription("Close Diff View"); + } + } + + private boolean activateDiffProgram() { + + Program currentProgram = plugin.getCurrentProgram(); + Program firstProgram = plugin.getFirstProgram(); + boolean isFirstProgram = (firstProgram == currentProgram); + if (isFirstProgram) { + return false; // already active--nothing to do! + } + + plugin.activeProgram(firstProgram); + return true; + } + } } diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java index 29dc54331a..3d26cbb5c1 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java @@ -20,6 +20,7 @@ import java.awt.event.*; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.*; +import java.util.List; import javax.swing.*; import javax.swing.text.*; @@ -59,8 +60,7 @@ import ghidra.program.model.address.*; import ghidra.program.model.listing.*; import ghidra.program.util.*; import ghidra.util.*; -import ghidra.util.exception.CancelledException; -import ghidra.util.exception.VersionException; +import ghidra.util.exception.*; import ghidra.util.task.*; import help.Help; import help.HelpService; @@ -82,7 +82,8 @@ import help.HelpService; "the current program. This plugin also computes differences between the two " + "programs and allows the user to apply differences from the second program onto" + "the first.", - servicesRequired = { GoToService.class, CodeViewerService.class, MarkerService.class }, + servicesRequired = { GoToService.class, CodeViewerService.class, MarkerService.class, + ProgramManager.class }, servicesProvided = { DiffService.class }, eventsProduced = { ProgramSelectionPluginEvent.class, ViewChangedPluginEvent.class }, eventsConsumed = { ProgramClosedPluginEvent.class, ViewChangedPluginEvent.class } @@ -101,6 +102,7 @@ public class ProgramDiffPlugin extends ProgramPlugin private Color cursorHighlightColor = GhidraOptions.DEFAULT_CURSOR_LINE_COLOR; protected static final HelpService help = Help.getHelpService(); + private ProgramManager programManagerService; private GoToService goToService; private CodeViewerService codeViewerService; private MarkerManager markerManager; @@ -139,7 +141,6 @@ public class ProgramDiffPlugin extends ProgramPlugin private DiffDetailsProvider diffDetailsProvider; private boolean settingLocation; - private ActionListener okListener; private DiffTaskListener diffTaskListener = DiffTaskListener.NULL_LISTENER; private ProgramLocation previousP1Location; @@ -148,7 +149,7 @@ public class ProgramDiffPlugin extends ProgramPlugin DiffApplySettingsOptionManager applySettingsMgr; private boolean isHighlightCursorLine; private Program activeProgram; - private OpenVersionedFileDialog openProgramDialog; + private OpenVersionedFileDialog openVersionedFileDialog; /** * Creates the plugin for indicating program differences to the user. @@ -289,7 +290,11 @@ public class ProgramDiffPlugin extends ProgramPlugin ProgramSelection previousP2DiffHighlight = p2DiffHighlight; ProgramSelection previousP2Selection = p2Selection; + AddressSet p2ViewAddrSet = + DiffUtility.getCompatibleAddressSet(p1ViewAddrSet, secondaryDiffProgram); + diffListingPanel.setView(p2ViewAddrSet); FieldPanel fp = diffListingPanel.getFieldPanel(); + AddressSet p1AddressSetAsP2 = DiffUtility.getCompatibleAddressSet(p1AddressSet, secondaryDiffProgram); AddressIndexMap p2IndexMap = new AddressIndexMap(p1AddressSetAsP2); @@ -327,8 +332,8 @@ public class ProgramDiffPlugin extends ProgramPlugin } @Override - public boolean inProgress() { - return taskInProgress; + public boolean isDiffActive() { + return secondaryDiffProgram != null; } private boolean launchDiffOnOpenProgram() { @@ -336,7 +341,7 @@ public class ProgramDiffPlugin extends ProgramPlugin if (diffControl != null) { // There is currently a Diff already so clear it. clearDiff(); } - diff(p1ViewAddrSet); + diff(); return true; } catch (Exception e) { @@ -347,6 +352,13 @@ public class ProgramDiffPlugin extends ProgramPlugin @Override public boolean launchDiff(DomainFile otherProgram) { + if (taskInProgress) { + Msg.error(this, "Diff is busy and can't be launched"); + return false; + } + if (isDiffActive()) { + closeProgram2(); + } if (openSecondProgram(otherProgram)) { return launchDiffOnOpenProgram(); } @@ -355,20 +367,18 @@ public class ProgramDiffPlugin extends ProgramPlugin @Override public boolean launchDiff(Program otherProgram) { - try { - if (diffControl != null) { // There is currently a Diff already so clear it. - clearDiff(); - } - if (openSecondProgram(otherProgram, null)) { - secondaryDiffProgram.addConsumer(this); - diff(p1ViewAddrSet); - } - return true; - } - catch (Exception e) { - Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); + if (taskInProgress) { + Msg.error(this, "Diff is busy and can't be launched"); return false; } + if (isDiffActive()) { + closeProgram2(); + } + otherProgram.addConsumer(this); + if (openSecondProgram(otherProgram, null)) { + launchDiffOnOpenProgram(); + } + return true; } @Override @@ -487,8 +497,12 @@ public class ProgramDiffPlugin extends ProgramPlugin } } - void setOpenDiffProgramDialog(OpenVersionedFileDialog dialog) { - this.openProgramDialog = dialog; + /** + * Used for testing to force file selection dialog instance. + * @param dialog project file selection dialog + */ + void setDiffOpenVersionedFileDialog(OpenVersionedFileDialog dialog) { + this.openVersionedFileDialog = dialog; } private void setActiveProgram(Program newActiveProgram) { @@ -575,6 +589,7 @@ public class ProgramDiffPlugin extends ProgramPlugin protected void init() { codeViewerService = tool.getService(CodeViewerService.class); goToService = tool.getService(GoToService.class); + programManagerService = tool.getService(ProgramManager.class); FormatManager formatManager = codeViewerService.getFormatManager(); ServiceProvider diffServiceProvider = @@ -934,21 +949,11 @@ public class ProgramDiffPlugin extends ProgramPlugin updatePgm2Enablement(); } - /** - * Computes the differences between program1 and program2 that are displayed in the browser - * using the current Limiting set. It allows the user to specify the Diff settings to use. - */ - void diff() { - diff(createLimitingSet()); - } - /** * Computes the differences between program1 and program2 that are displayed in the browser. It * allows the user to specify the Diff settings to use. - * - * @param p1LimitSet an address set to use to limit the extent of the Diff. */ - void diff(AddressSetView p1LimitSet) { + void diff() { if (taskInProgress) { Msg.showInfo(getClass(), tool.getToolFrame(), "Can't Start Another Diff", "A Diff or Apply is already in progress."); @@ -956,10 +961,10 @@ public class ProgramDiffPlugin extends ProgramPlugin } boolean reload = diffControl != null; if (reload) { - reloadDiff(p1LimitSet); + reloadDiff(); } else { - createDiff(p1LimitSet); + createDiff(); } } @@ -1087,23 +1092,60 @@ public class ProgramDiffPlugin extends ProgramPlugin return; } - final OpenVersionedFileDialog dialog = getOpenProgramDialog(); - okListener = e -> { + selectAndOpenProgram2(); + + actionManager.setOpenCloseActionSelected(secondaryDiffProgram != null); + getDiffDetailsProvider(); + } + + /** + * Generate a list of programs which are currently open in the tool which are compatible + * with the primaryProgram to be diff'd. The top/primary entries correspond to this + * programs which have the same name (see {@link Program#getName()}) as the primaryProgram, + * while the remaining compatible programs will be considered secondary. Each of these + * two groups will be sorted by its domain file name then concatenated to form a single list. + * @return ordered open program list for use with the {@link OpenVersionedFileDialog}. + */ + private List getOpenProgramList() { + List primaryList = new ArrayList<>(); + List secondaryList = new ArrayList<>(); + for (Program p : programManagerService.getAllOpenPrograms()) { + if (!programManagerService.isVisible(p) || p == activeProgram || + !ProgramMemoryComparator.similarPrograms(activeProgram, p)) { + continue; + } + if (p.getName().equals(activeProgram.getName())) { + primaryList.add(p); + } + else { + secondaryList.add(p); + } + } + Comparator programComparator = (a, b) -> { + return a.getDomainFile().getName().compareTo(b.getDomainFile().getName()); + }; + Collections.sort(primaryList, programComparator); + Collections.sort(secondaryList, programComparator); + + List programList = new ArrayList<>(); + programList.addAll(primaryList); + programList.addAll(secondaryList); + return programList; + } + + private void selectAndOpenProgram2() { + final OpenVersionedFileDialog dialog = getOpenVersionedFileDialog(); + + List openProgramList = getOpenProgramList(); + dialog.setOpenObjectChoices(openProgramList.isEmpty() ? null : openProgramList); + + dialog.addOkActionListener(e -> { tool.clearStatusInfo(); JComponent component = dialog.getComponent(); - DomainObject dobj = dialog.getVersionedDomainObject(ProgramDiffPlugin.this, false); + Program dobj = dialog.getDomainObject(ProgramDiffPlugin.this, false); if (dobj != null) { - if (openSecondProgram((Program) dobj, component)) { - dialog.close(); - launchDiffOnOpenProgram(); - } - return; - } - - DomainFile df = dialog.getDomainFile(); - if (df != null) { - if (openSecondProgram(df)) { + if (openSecondProgram(dobj, component)) { dialog.close(); launchDiffOnOpenProgram(); } @@ -1112,25 +1154,18 @@ public class ProgramDiffPlugin extends ProgramPlugin displayStatus(component, "Can't Open Selected Program", "Please select a file, not a folder.", OptionDialog.INFORMATION_MESSAGE); - }; - dialog.addOkActionListener(okListener); - + }); dialog.showComponent(); - actionManager.setOpenCloseActionSelected(secondaryDiffProgram != null); - getDiffDetailsProvider(); } - private OpenVersionedFileDialog getOpenProgramDialog() { + private OpenVersionedFileDialog getOpenVersionedFileDialog() { - if (openProgramDialog != null) { - return openProgramDialog; + if (openVersionedFileDialog != null) { + return openVersionedFileDialog; } - OpenVersionedFileDialog dialog = - new OpenVersionedFileDialog(tool, "Select Other Program", f -> { - Class c = f.getDomainObjectClass(); - return Program.class.isAssignableFrom(c); - }); + OpenVersionedFileDialog dialog = + new OpenVersionedFileDialog<>(tool, "Select Other Program", Program.class); dialog.setTreeSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); dialog.setHelpLocation(new HelpLocation("Diff", "Open_Close_Program_View")); return dialog; @@ -1144,12 +1179,10 @@ public class ProgramDiffPlugin extends ProgramPlugin executeDiffDialog = new ExecuteDiffDialog(); executeDiffDialog.addActionListener(new DiffActionListener()); } - if (executeDiffDialog != null) { - executeDiffDialog.configure(primaryProgram, secondaryDiffProgram, currentSelection, - execDiffFilter); - executeDiffDialog.setPgmContextEnabled(sameProgramContext); - tool.showDialog(executeDiffDialog); - } + executeDiffDialog.configure(primaryProgram, secondaryDiffProgram, currentSelection, + execDiffFilter); + executeDiffDialog.setPgmContextEnabled(sameProgramContext); + tool.showDialog(executeDiffDialog); } void setP1SelectionOnP2() { @@ -1252,7 +1285,7 @@ public class ProgramDiffPlugin extends ProgramPlugin if (primaryProgram == null) { return null; } - if (executeDiffDialog != null) { + if (executeDiffDialog != null) { // TODO: don't reuse if it could change return executeDiffDialog.getAddressSet(); } AddressSet limitSet = new AddressSet(primaryProgram.getMemory()); @@ -1266,38 +1299,29 @@ public class ProgramDiffPlugin extends ProgramPlugin /** * Reload the marked differences in the diff panel. */ - private void reloadDiff(AddressSetView p1LimitSet) { + private void reloadDiff() { if (diffControl == null) { - createDiff(p1LimitSet); + createDiff(); } else { tool.clearStatusInfo(); - if (p1LimitSet == null) { - p1LimitSet = createLimitingSet(); - } displayExecuteDiff(); } } - private void createDiff(AddressSetView p1LimitSet) { + private void createDiff() { Frame frame = tool.getToolFrame(); try { frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); tool.clearStatusInfo(); if (secondaryDiffProgram == null) { - selectProgram2(); - if (secondaryDiffProgram == null) { - return; - } + throw new AssertException("Expected secondaryDiffProgram"); } if (executeDiffDialog != null) { executeDiffDialog.close(); executeDiffDialog = null; } - if (p1LimitSet == null) { - p1LimitSet = createLimitingSet(); - } displayExecuteDiff(); } finally { @@ -1521,29 +1545,29 @@ public class ProgramDiffPlugin extends ProgramPlugin return false; } - private boolean openSecondProgram(Program newProgram, JComponent selectDialog) { + private boolean openSecondProgram(Program newProgram, JComponent popupParent) { if (newProgram == null) { - displayStatus(selectDialog, "Can't Open Selected Program", + displayStatus(popupParent, "Can't Open Selected Program", "Couldn't open second program.", OptionDialog.ERROR_MESSAGE); return false; } if (!ProgramMemoryComparator.similarPrograms(currentProgram, newProgram)) { - newProgram.release(this); String message = "Programs languages don't match.\n" + currentProgram.getName() + " (" + currentProgram.getLanguageID() + ")\n" + newProgram.getName() + " (" + newProgram.getLanguageID() + ")"; - displayStatus(selectDialog, "Can't Open Selected Program", message, + displayStatus(popupParent, "Can't Open Selected Program", message, OptionDialog.ERROR_MESSAGE); + newProgram.release(this); return false; } ProgramMemoryComparator programMemoryComparator = null; try { - programMemoryComparator = new ProgramMemoryComparator(currentProgram, newProgram); } catch (ProgramConflictException e) { Msg.error(this, "Unexpected exception creating memory comparator", e); + newProgram.release(this); return false; } addressesOnlyInP1 = programMemoryComparator.getAddressesOnlyInOne(); @@ -1552,7 +1576,7 @@ public class ProgramDiffPlugin extends ProgramPlugin AddressSet combinedAddresses = ProgramMemoryComparator.getCombinedAddresses(currentProgram, newProgram); if (addressesInCommon.isEmpty()) { - int selectedOption = OptionDialog.showYesNoDialog(selectDialog, "No Memory In Common", + int selectedOption = OptionDialog.showYesNoDialog(popupParent, "No Memory In Common", "The two programs have no memory addresses in common.\n" + "Do you want to continue?"); if (selectedOption != OptionDialog.YES_OPTION) { diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/services/DiffService.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/services/DiffService.java index dbf9a10065..6a67a369fa 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/services/DiffService.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/services/DiffService.java @@ -30,23 +30,29 @@ public interface DiffService { /** * Launch the Diff dialog and display differences between the current program - * and the otherProgram. + * and the otherProgram. This will force the current Diff, if active, to be terminated. * @param otherProgram a domain file for the program to Diff the current program against. - * @return true if the second program is opened and successfully Diffed. + * @return true if the second program is opened and successfully Diffed. A false will be + * returned if the Diff fails to launch. */ public boolean launchDiff(DomainFile otherProgram); /** * Launch the Diff dialog and display differences between the current program - * and the otherProgram. + * and the otherProgram. This will force the current Diff, if active, to be terminated. + * This Diff service will be added as a consumer on the specified otherProgram while the Diff + * remains active. * @param otherProgram the program to Diff the current program against. - * @return true if the second program is opened and successfully Diffed. + * @return true if the second program is opened and successfully Diffed. A false will be + * returned if the Diff fails to launch. */ public boolean launchDiff(Program otherProgram); /** - * Determine if the Diff service is currently displaying a Diff. + * Determine if the Diff service is currently displaying a Diff within the Tool associated with + * this service. + * @return true if a Diff is currently active */ - public boolean inProgress(); + public boolean isDiffActive(); } diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java index 2987ff4916..29fe6236f2 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java @@ -56,7 +56,7 @@ public class DiffSaveSettingsTest extends DiffApplyTestAdapter { diffListingPanel = diffPlugin.getListingPanel(); fp1 = cb.getFieldPanel(); fp2 = diffListingPanel.getFieldPanel(); - openClosePgm2 = (ToggleDockingAction) getAction(diffPlugin, "Open/Close Program View"); + openClosePgm2 = (ToggleDockingAction) getAction(diffPlugin, "Open/Close Diff View"); } private void showNewTool() throws Exception { @@ -73,7 +73,7 @@ public class DiffSaveSettingsTest extends DiffApplyTestAdapter { diffListingPanel = diffPlugin.getListingPanel(); fp1 = cb.getFieldPanel(); fp2 = diffListingPanel.getFieldPanel(); - openClosePgm2 = (ToggleDockingAction) getAction(diffPlugin, "Open/Close Program View"); + openClosePgm2 = (ToggleDockingAction) getAction(diffPlugin, "Open/Close Diff View"); } @Override diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTest.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTest.java index b4ed548e7e..f0c01a99c8 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTest.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTest.java @@ -659,7 +659,7 @@ public class DiffTest extends DiffTestAdapter { assertEquals(true, isShowingDiff()); // Check action enablement. checkDiffAction("View Program Differences", true, true); - checkDiffAction("Open/Close Program View", true, true); + checkDiffAction("Open/Close Diff View", true, true); checkDiffAction("Apply Differences", true, false); checkDiffAction("Apply Differences and Goto Next Difference", true, false); checkDiffAction("Ignore Selection and Goto Next Difference", true, false); @@ -777,13 +777,13 @@ public class DiffTest extends DiffTestAdapter { assertEquals(true, isDiffing()); assertEquals(true, isShowingDiff()); - checkDiffAction("Open/Close Program View", true, true); + checkDiffAction("Open/Close Diff View", true, true); // // Different tab--still enabled // selectTab(panel, program3); - checkDiffAction("Open/Close Program View", true, true); + checkDiffAction("Open/Close Diff View", true, true); clickDiffButton(); assertTrue("Not diffing after clicking the diff button when on a non-diff tab", @@ -794,7 +794,7 @@ public class DiffTest extends DiffTestAdapter { // // Diff tab--still enabled // - checkDiffAction("Open/Close Program View", true, true); + checkDiffAction("Open/Close Diff View", true, true); clickDiffButton(); diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java index ac7f16fff2..405b2b5ede 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java @@ -43,7 +43,8 @@ import ghidra.app.plugin.core.programtree.ProgramTreePlugin; import ghidra.app.services.ProgramManager; import ghidra.app.util.viewer.listingpanel.ListingPanel; import ghidra.framework.main.*; -import ghidra.framework.model.*; +import ghidra.framework.model.DomainFile; +import ghidra.framework.model.DomainFolder; import ghidra.framework.plugintool.PluginTool; import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramDB; @@ -479,7 +480,7 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { diffListingPanel = diffPlugin.getListingPanel(); fp1 = cb.getFieldPanel(); fp2 = diffListingPanel.getFieldPanel(); - openClosePgm2 = (ToggleDockingAction) getAction(diffPlugin, "Open/Close Program View"); + openClosePgm2 = (ToggleDockingAction) getAction(diffPlugin, "Open/Close Diff View"); tool.addPlugin(ProgramTreePlugin.class.getName()); pt = env.getPlugin(ProgramTreePlugin.class); @@ -664,10 +665,8 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { void pickSecondProgram(final Program program2) { - program2.addConsumer(diffPlugin); - OpenVersionedFileDialogTestFake dialog = new OpenVersionedFileDialogTestFake(program2); - diffPlugin.setOpenDiffProgramDialog(dialog); + diffPlugin.setDiffOpenVersionedFileDialog(dialog); launchDiffByAction(); @@ -1154,13 +1153,13 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { // Inner Classes //================================================================================================== - private class OpenVersionedFileDialogTestFake extends OpenVersionedFileDialog { + private class OpenVersionedFileDialogTestFake extends OpenVersionedFileDialog { private ActionListener listener; private Program chosenProgram; OpenVersionedFileDialogTestFake(Program program) { - super(tool, "Select Other Program", null); + super(tool, "Select Other Program", Program.class); this.chosenProgram = program; } @@ -1183,7 +1182,10 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { } @Override - public DomainObject getVersionedDomainObject(Object consumer, boolean readOnly) { + public Program getDomainObject(Object consumer, boolean readOnly) { + if (chosenProgram != null) { + chosenProgram.addConsumer(consumer); + } return chosenProgram; } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/LinkHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/LinkHandler.java index f9e65aacd5..110482a6c3 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/LinkHandler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/LinkHandler.java @@ -135,7 +135,9 @@ public abstract class LinkHandler extends DBCon @Override public T getImmutableObject(FolderItem item, Object consumer, int version, int minChangeVersion, TaskMonitor monitor) throws IOException, CancelledException, VersionException { - throw new UnsupportedOperationException("link-file does not support getImmutableObject"); + //throw new UnsupportedOperationException("link-file does not support getImmutableObject"); + // See GP-2903 + return getReadOnlyObject(item, version, true, consumer, monitor); } @Override diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/DefaultProject.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/DefaultProject.java index 3ea00eebac..71b72a1790 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/DefaultProject.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/DefaultProject.java @@ -497,7 +497,8 @@ public class DefaultProject implements Project { addProjectView(url, true); } catch (IOException e) { - Msg.error(this, e.getMessage()); + Msg.error(this, "Project view not opended (" + GhidraURL.getDisplayString(url) + + "): " + e.getMessage()); } } it = root.getChildren(OPEN_REPOSITORY_VIEW_XML_NAME).iterator(); @@ -509,7 +510,8 @@ public class DefaultProject implements Project { addProjectView(url, true); } catch (IOException e) { - Msg.error(this, e.getMessage()); + Msg.error(this, "Project view not opended (" + GhidraURL.getDisplayString(url) + + "): " + e.getMessage()); } } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DiffScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DiffScreenShots.java index bbcbab9d2e..b43abc176d 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DiffScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DiffScreenShots.java @@ -45,8 +45,7 @@ public class DiffScreenShots extends GhidraScreenShotGenerator { public void testSelectOtherProgram() throws Exception { addProgramsToProject(); program = env.getProgram("WinHelloCPP.exe"); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); + performAction("Open/Close Diff View", "ProgramDiffPlugin", false); waitForSwing(); DialogComponentProvider dialog = getDialog(); captureDialog(dialog.getPreferredSize().width, 500); @@ -59,10 +58,10 @@ public class DiffScreenShots extends GhidraScreenShotGenerator { addProgramsToProject(); createProgramVersions(); waitForSwing(); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); + performAction("Open/Close Diff View", "ProgramDiffPlugin", false); waitForSwing(); - OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); + @SuppressWarnings("unchecked") + OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); DataTree dataTree = (DataTree) findComponentByName(dialog.getComponent(), "Data Tree"); selectPath(dataTree, env.getProject().getName(), "WinHelloCpp.exe"); JButton historyButton = findButtonByText(dialog.getComponent(), "History>>"); @@ -70,13 +69,34 @@ public class DiffScreenShots extends GhidraScreenShotGenerator { captureDialog(); } + @Test + public void testSelectOpenProgram() throws Exception { + addProgramsToProject(); + createProgramVersions(); + runSwing(() -> { + Project project = env.getProject(); + ProjectData projectData = project.getProjectData(); + DomainFile file = projectData.getRootFolder().getFile("OldWinHelloCpp.exe"); + ProgramManager pm = tool.getService(ProgramManager.class); + pm.openProgram(file); + }); + waitForSwing(); + performAction("Open/Close Diff View", "ProgramDiffPlugin", false); + waitForSwing(); + @SuppressWarnings("unchecked") + OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); + JTabbedPane tabPane = (JTabbedPane) findComponentByName(dialog.getComponent(), "Tabs"); + runSwing(() -> tabPane.setSelectedIndex(1)); // select Open Programs tab + captureDialog(dialog.getPreferredSize().width, 500); + } + @Test public void testDetermineDiffs() throws Exception { addProgramsToProject(); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); + performAction("Open/Close Diff View", "ProgramDiffPlugin", false); waitForSwing(); - OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); + @SuppressWarnings("unchecked") + OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); DataTree dataTree = (DataTree) findComponentByName(dialog.getComponent(), "Data Tree"); selectPath(dataTree, env.getProject().getName(), "WinHelloCpp.exe"); waitForSwing(); @@ -89,10 +109,10 @@ public class DiffScreenShots extends GhidraScreenShotGenerator { public void testDiff() throws Exception { addProgramsToProject(); createDifferences(); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); + performAction("Open/Close Diff View", "ProgramDiffPlugin", false); waitForSwing(); - OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); + @SuppressWarnings("unchecked") + OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); DataTree dataTree = (DataTree) findComponentByName(dialog.getComponent(), "Data Tree"); selectPath(dataTree, env.getProject().getName(), "WinHelloCpp.exe"); waitForSwing(); @@ -111,10 +131,10 @@ public class DiffScreenShots extends GhidraScreenShotGenerator { public void testDiffApplySettings() throws Exception { addProgramsToProject(); createDifferences(); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); + performAction("Open/Close Diff View", "ProgramDiffPlugin", false); waitForSwing(); - OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); + @SuppressWarnings("unchecked") + OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); DataTree dataTree = (DataTree) findComponentByName(dialog.getComponent(), "Data Tree"); selectPath(dataTree, env.getProject().getName(), "WinHelloCpp.exe"); waitForSwing(); @@ -149,10 +169,10 @@ public class DiffScreenShots extends GhidraScreenShotGenerator { public void testDiffDetails() throws Exception { addProgramsToProject(); createDifferencesAt401417(); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); - performAction("Open/Close Program View", "ProgramDiffPlugin", false); + performAction("Open/Close Diff View", "ProgramDiffPlugin", false); waitForSwing(); - OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); + @SuppressWarnings("unchecked") + OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); DataTree dataTree = (DataTree) findComponentByName(dialog.getComponent(), "Data Tree"); selectPath(dataTree, env.getProject().getName(), "WinHelloCpp.exe"); waitForSwing();