From 05fb77e9bd28c363d6e817a68f09d6bd45307645 Mon Sep 17 00:00:00 2001 From: Iscle Date: Mon, 8 Jul 2024 19:36:45 +0200 Subject: [PATCH] feat(gui): add button to go to Application class (#2208)(PR #2213) * feat: Add button to go to Application class Icons from: https://intellij-icons.jetbrains.design/ * fix: Rename "goto" to "go_to" to keep things consistent --- .../utils/android/AndroidManifestParser.java | 14 ++++- .../jadx/core/utils/android/AppAttribute.java | 1 + .../core/utils/android/ApplicationParams.java | 16 ++++-- .../jadx/gui/device/debugger/DbgUtils.java | 4 +- .../src/main/java/jadx/gui/ui/MainWindow.java | 53 +++++++++++++++---- .../java/jadx/gui/ui/action/ActionModel.java | 4 +- .../resources/i18n/Messages_de_DE.properties | 3 +- .../resources/i18n/Messages_en_US.properties | 3 +- .../resources/i18n/Messages_es_ES.properties | 3 +- .../resources/i18n/Messages_id_ID.properties | 3 +- .../resources/i18n/Messages_ko_KR.properties | 3 +- .../resources/i18n/Messages_pt_BR.properties | 3 +- .../resources/i18n/Messages_ru_RU.properties | 5 +- .../resources/i18n/Messages_zh_CN.properties | 3 +- .../resources/i18n/Messages_zh_TW.properties | 3 +- .../main/resources/icons/ui/application.svg | 6 +++ 16 files changed, 101 insertions(+), 26 deletions(-) create mode 100644 jadx-gui/src/main/resources/icons/ui/application.svg diff --git a/jadx-core/src/main/java/jadx/core/utils/android/AndroidManifestParser.java b/jadx-core/src/main/java/jadx/core/utils/android/AndroidManifestParser.java index 3982a5aaf..9276669ac 100644 --- a/jadx-core/src/main/java/jadx/core/utils/android/AndroidManifestParser.java +++ b/jadx-core/src/main/java/jadx/core/utils/android/AndroidManifestParser.java @@ -65,6 +65,7 @@ public class AndroidManifestParser { Integer versionCode = null; String versionName = null; String mainActivity = null; + String application = null; Element manifest = (Element) androidManifest.getElementsByTagName("manifest").item(0); Element usesSdk = (Element) androidManifest.getElementsByTagName("uses-sdk").item(0); @@ -95,9 +96,12 @@ public class AndroidManifestParser { if (parseAttrs.contains(AppAttribute.MAIN_ACTIVITY)) { mainActivity = getMainActivityName(); } + if (parseAttrs.contains(AppAttribute.APPLICATION)) { + application = getApplicationName(); + } return new ApplicationParams(applicationLabel, minSdkVersion, targetSdkVersion, versionCode, - versionName, mainActivity); + versionName, mainActivity, application); } private String getApplicationLabel() { @@ -137,6 +141,14 @@ public class AndroidManifestParser { return mainActivityName; } + private String getApplicationName() { + Element application = (Element) androidManifest.getElementsByTagName("application").item(0); + if (application.hasAttribute("android:name")) { + return application.getAttribute("android:name"); + } + return null; + } + private String getMainActivityNameThroughActivityAliasTag() { NodeList activityAliasNodes = androidManifest.getElementsByTagName("activity-alias"); for (int i = 0; i < activityAliasNodes.getLength(); i++) { diff --git a/jadx-core/src/main/java/jadx/core/utils/android/AppAttribute.java b/jadx-core/src/main/java/jadx/core/utils/android/AppAttribute.java index 0fc9d7938..e4d23a654 100644 --- a/jadx-core/src/main/java/jadx/core/utils/android/AppAttribute.java +++ b/jadx-core/src/main/java/jadx/core/utils/android/AppAttribute.java @@ -7,4 +7,5 @@ public enum AppAttribute { VERSION_CODE, VERSION_NAME, MAIN_ACTIVITY, + APPLICATION, } diff --git a/jadx-core/src/main/java/jadx/core/utils/android/ApplicationParams.java b/jadx-core/src/main/java/jadx/core/utils/android/ApplicationParams.java index 8c904ffca..702a1a46c 100644 --- a/jadx-core/src/main/java/jadx/core/utils/android/ApplicationParams.java +++ b/jadx-core/src/main/java/jadx/core/utils/android/ApplicationParams.java @@ -11,15 +11,17 @@ public class ApplicationParams { private final Integer versionCode; private final String versionName; private final String mainActivtiy; + private final String application; public ApplicationParams(String applicationLabel, Integer minSdkVersion, Integer targetSdkVersion, Integer versionCode, - String versionName, String mainActivtiy) { + String versionName, String mainActivtiy, String application) { this.applicationLabel = applicationLabel; this.minSdkVersion = minSdkVersion; this.targetSdkVersion = targetSdkVersion; this.versionCode = versionCode; this.versionName = versionName; this.mainActivtiy = mainActivtiy; + this.application = application; } public String getApplicationName() { @@ -42,11 +44,19 @@ public class ApplicationParams { return versionName; } - public String getMainActivityName() { + public String getMainActivity() { return mainActivtiy; } - public JavaClass getMainActivity(JadxDecompiler decompiler) { + public JavaClass getMainActivityJavaClass(JadxDecompiler decompiler) { return decompiler.searchJavaClassByOrigFullName(mainActivtiy); } + + public String getApplication() { + return application; + } + + public JavaClass getApplicationJavaClass(JadxDecompiler decompiler) { + return decompiler.searchJavaClassByOrigFullName(application); + } } diff --git a/jadx-gui/src/main/java/jadx/gui/device/debugger/DbgUtils.java b/jadx-gui/src/main/java/jadx/gui/device/debugger/DbgUtils.java index 3935a0aa8..e77a02356 100644 --- a/jadx-gui/src/main/java/jadx/gui/device/debugger/DbgUtils.java +++ b/jadx-gui/src/main/java/jadx/gui/device/debugger/DbgUtils.java @@ -154,7 +154,7 @@ public class DbgUtils { return null; } ApplicationParams results = parser.parse(); - String mainActivityName = results.getMainActivityName(); + String mainActivityName = results.getMainActivity(); if (mainActivityName == null) { UiUtils.errorMessage(mw, NLS.str("adb_dialog.msg_read_mani_fail")); return null; @@ -163,7 +163,7 @@ public class DbgUtils { UiUtils.errorMessage(mw, "Invalid main activity name"); return null; } - JavaClass mainActivityClass = results.getMainActivity(decompiler); + JavaClass mainActivityClass = results.getMainActivityJavaClass(decompiler); if (mainActivityClass == null) { UiUtils.errorMessage(mw, NLS.str("error_dialog.not_found", "Main activity class")); return null; diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java index 6a7e6f512..ae01e65e2 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -952,7 +952,7 @@ public class MainWindow extends JFrame { SearchDialog.search(MainWindow.this, SearchDialog.SearchPreset.TEXT); } - public void gotoMainActivity() { + public void goToMainActivity() { AndroidManifestParser parser = new AndroidManifestParser( AndroidManifestParser.getAndroidManifest(getWrapper().getResources()), EnumSet.of(AppAttribute.MAIN_ACTIVITY)); @@ -965,12 +965,12 @@ public class MainWindow extends JFrame { } try { ApplicationParams results = parser.parse(); - if (results.getMainActivityName() == null) { + if (results.getMainActivity() == null) { throw new JadxRuntimeException("Failed to get main activity name from manifest"); } - JavaClass mainActivityClass = results.getMainActivity(getWrapper().getDecompiler()); + JavaClass mainActivityClass = results.getMainActivityJavaClass(getWrapper().getDecompiler()); if (mainActivityClass == null) { - throw new JadxRuntimeException("Failed to find main activity class: " + results.getMainActivityName()); + throw new JadxRuntimeException("Failed to find main activity class: " + results.getMainActivity()); } tabbedPane.codeJump(getCacheObject().getNodeCache().makeFrom(mainActivityClass)); } catch (Exception e) { @@ -982,6 +982,36 @@ public class MainWindow extends JFrame { } } + public void goToApplication() { + AndroidManifestParser parser = new AndroidManifestParser( + AndroidManifestParser.getAndroidManifest(getWrapper().getResources()), + EnumSet.of(AppAttribute.APPLICATION)); + if (!parser.isManifestFound()) { + JOptionPane.showMessageDialog(MainWindow.this, + NLS.str("error_dialog.not_found", "AndroidManifest.xml"), + NLS.str("error_dialog.title"), + JOptionPane.ERROR_MESSAGE); + return; + } + try { + ApplicationParams results = parser.parse(); + if (results.getApplication() == null) { + throw new JadxRuntimeException("Failed to get application from manifest"); + } + JavaClass applicationClass = results.getApplicationJavaClass(getWrapper().getDecompiler()); + if (applicationClass == null) { + throw new JadxRuntimeException("Failed to find application class: " + results.getApplication()); + } + tabbedPane.codeJump(getCacheObject().getNodeCache().makeFrom(applicationClass)); + } catch (Exception e) { + LOG.error("Application not found", e); + JOptionPane.showMessageDialog(MainWindow.this, + NLS.str("error_dialog.not_found", "Application"), + NLS.str("error_dialog.title"), + JOptionPane.ERROR_MESSAGE); + } + } + private void initMenuAndToolbar() { JadxGuiAction openAction = new JadxGuiAction(ActionModel.OPEN, this::openFileDialog); JadxGuiAction openProject = new JadxGuiAction(ActionModel.OPEN_PROJECT, this::openProjectDialog); @@ -1036,8 +1066,10 @@ public class MainWindow extends JFrame { () -> SearchDialog.search(MainWindow.this, SearchDialog.SearchPreset.CLASS)); JadxGuiAction commentSearchAction = new JadxGuiAction(ActionModel.COMMENT_SEARCH, () -> SearchDialog.search(MainWindow.this, SearchDialog.SearchPreset.COMMENT)); - JadxGuiAction gotoMainActivityAction = new JadxGuiAction(ActionModel.GOTO_MAIN_ACTIVITY, - this::gotoMainActivity); + JadxGuiAction goToMainActivityAction = new JadxGuiAction(ActionModel.GO_TO_MAIN_ACTIVITY, + this::goToMainActivity); + JadxGuiAction goToApplicationAction = new JadxGuiAction(ActionModel.GO_TO_APPLICATION, + this::goToApplication); JadxGuiAction decompileAllAction = new JadxGuiAction(ActionModel.DECOMPILE_ALL, this::requestFullDecompilation); JadxGuiAction resetCacheAction = new JadxGuiAction(ActionModel.RESET_CACHE, this::resetCodeCache); JadxGuiAction deobfAction = new JadxGuiAction(ActionModel.DEOBF, this::toggleDeobfuscation); @@ -1097,7 +1129,8 @@ public class MainWindow extends JFrame { nav.add(textSearchAction); nav.add(clsSearchAction); nav.add(commentSearchAction); - nav.add(gotoMainActivityAction); + nav.add(goToMainActivityAction); + nav.add(goToApplicationAction); nav.addSeparator(); nav.add(backAction); nav.add(forwardAction); @@ -1162,7 +1195,8 @@ public class MainWindow extends JFrame { toolbar.add(textSearchAction); toolbar.add(clsSearchAction); toolbar.add(commentSearchAction); - toolbar.add(gotoMainActivityAction); + toolbar.add(goToMainActivityAction); + toolbar.add(goToApplicationAction); toolbar.addSeparator(); toolbar.add(backAction); toolbar.add(forwardAction); @@ -1190,7 +1224,8 @@ public class MainWindow extends JFrame { textSearchAction.setEnabled(loaded); clsSearchAction.setEnabled(loaded); commentSearchAction.setEnabled(loaded); - gotoMainActivityAction.setEnabled(loaded); + goToMainActivityAction.setEnabled(loaded); + goToApplicationAction.setEnabled(loaded); backAction.setEnabled(loaded); backVariantAction.setEnabled(loaded); forwardAction.setEnabled(loaded); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/action/ActionModel.java b/jadx-gui/src/main/java/jadx/gui/ui/action/ActionModel.java index 7f8747e8b..e315af301 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/action/ActionModel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/action/ActionModel.java @@ -51,8 +51,10 @@ public enum ActionModel { Shortcut.keyboard(KeyEvent.VK_N, UiUtils.ctrlButton())), COMMENT_SEARCH(MENU_TOOLBAR, "menu.comment_search", "menu.comment_search", "ui/usagesFinder", Shortcut.keyboard(KeyEvent.VK_SEMICOLON, UiUtils.ctrlButton() | KeyEvent.SHIFT_DOWN_MASK)), - GOTO_MAIN_ACTIVITY(MENU_TOOLBAR, "menu.goto_main_activity", "menu.goto_main_activity", "ui/home", + GO_TO_MAIN_ACTIVITY(MENU_TOOLBAR, "menu.go_to_main_activity", "menu.go_to_main_activity", "ui/home", Shortcut.keyboard(KeyEvent.VK_M, UiUtils.ctrlButton() | KeyEvent.SHIFT_DOWN_MASK)), + GO_TO_APPLICATION(MENU_TOOLBAR, "menu.go_to_application", "menu.go_to_application", "ui/application", + Shortcut.keyboard(KeyEvent.VK_A, UiUtils.ctrlButton() | KeyEvent.SHIFT_DOWN_MASK)), DECOMPILE_ALL(MENU_TOOLBAR, "menu.decompile_all", "menu.decompile_all", "ui/runAll", Shortcut.none()), RESET_CACHE(MENU_TOOLBAR, "menu.reset_cache", "menu.reset_cache", "ui/reset", diff --git a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties index 7e880ca58..372662353 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties @@ -14,7 +14,8 @@ menu.navigation=Navigation menu.text_search=Textsuche menu.class_search=Klassen-Suche menu.comment_search=Kommentar suchen -#menu.goto_main_activity= +#menu.go_to_main_activity= +#menu.go_to_application=Go to Application menu.tools=Tools #menu.plugins=Plugins #menu.decompile_all=Decompile all classes diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 3ab35079e..0cda42609 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -14,7 +14,8 @@ menu.navigation=Navigation menu.text_search=Text search menu.class_search=Class search menu.comment_search=Comment search -menu.goto_main_activity=Go to main Activity +menu.go_to_main_activity=Go to main Activity +menu.go_to_application=Go to Application menu.tools=Tools menu.plugins=Plugins menu.decompile_all=Decompile all classes diff --git a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties index d9717de4c..a57479aa6 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties @@ -14,7 +14,8 @@ menu.navigation=Navegación menu.text_search=Buscar texto menu.class_search=Buscar clase #menu.comment_search=Comment search -#menu.goto_main_activity= +#menu.go_to_main_activity= +#menu.go_to_application=Go to Application menu.tools=Herramientas #menu.plugins=Plugins #menu.decompile_all=Decompile all classes diff --git a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties index ac9763fae..0db70ace3 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties @@ -14,7 +14,8 @@ menu.navigation=Navigasi menu.text_search=Pencarian Teks menu.class_search=Pencarian Kelas menu.comment_search=Pencarian Komentar -menu.goto_main_activity=Pergi ke Activitas Utama +menu.go_to_main_activity=Pergi ke Activitas Utama +#menu.go_to_application=Go to Application menu.tools=Alat menu.plugins=Plugin menu.decompile_all=Deskompilasi semua kelas diff --git a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties index 5b839ce14..c0685fabb 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties @@ -14,7 +14,8 @@ menu.navigation=네비게이션 menu.text_search=텍스트 검색 menu.class_search=클래스 검색 menu.comment_search=주석 검색 -#menu.goto_main_activity= +#menu.go_to_main_activity= +#menu.go_to_application=Go to Application menu.tools=도구 #menu.plugins=Plugins #menu.decompile_all=Decompile all classes diff --git a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties index f674617b1..300cf9072 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties @@ -14,7 +14,8 @@ menu.navigation=Navegação menu.text_search=Buscar por texto menu.class_search=Buscar por classe menu.comment_search=Busca por comentário -#menu.goto_main_activity= +#menu.go_to_main_activity= +#menu.go_to_application=Go to Application menu.tools=Ferramentas #menu.plugins=Plugins #menu.decompile_all=Decompile all classes diff --git a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties index 20d03c684..a901b9fbd 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties @@ -14,7 +14,8 @@ menu.navigation=Навигация menu.text_search=Поиск строк menu.class_search=Поиск классов menu.comment_search=Поиск комментариев -menu.goto_main_activity=Найти главное Activity +menu.go_to_main_activity=Найти главное Activity +#menu.go_to_application=Go to Application menu.tools=Инструменты menu.plugins=Плагины menu.decompile_all=Декомпилировать все @@ -304,7 +305,7 @@ popup.remove=Удалить popup.add_files=Добавить файлы popup.add_scripts=Добавить скрипты popup.new_script=Новый скрипт -popup.json_prettify=Форматировать JSON +popup.json_prettify=Форматировать JSON script.run=Запустить script.save=Сохранить diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties index 9184852ff..3499a5f87 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties @@ -14,7 +14,8 @@ menu.navigation=导航 menu.text_search=文本搜索 menu.class_search=类名搜索 menu.comment_search=注释搜索 -menu.goto_main_activity=前往主 Activity +menu.go_to_main_activity=前往主 Activity +#menu.go_to_application=Go to Application menu.tools=工具 menu.plugins=插件 menu.decompile_all=反编译所有类 diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties index 8deea592d..5c1b6eb81 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties @@ -14,7 +14,8 @@ menu.navigation=瀏覽 menu.text_search=文字搜尋 menu.class_search=類別搜尋 menu.comment_search=註解搜尋 -menu.goto_main_activity=前往主 Activity +menu.go_to_main_activity=前往主 Activity +#menu.go_to_application=Go to Application menu.tools=工具 menu.plugins=外掛程式 menu.decompile_all=反編譯所有類別 diff --git a/jadx-gui/src/main/resources/icons/ui/application.svg b/jadx-gui/src/main/resources/icons/ui/application.svg new file mode 100644 index 000000000..4d4ed13ad --- /dev/null +++ b/jadx-gui/src/main/resources/icons/ui/application.svg @@ -0,0 +1,6 @@ + + + + + +