diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 769746f26e..5f48b17576 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -251,6 +251,11 @@ public final class app/revanced/patches/cieid/restrictions/root/BypassRootChecks public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/discord/misc/plugin/PluginLoaderPatch : app/revanced/patches/shared/misc/react/BaseReactPreloadScriptBootstrapperPatch { + public static final field INSTANCE Lapp/revanced/patches/discord/misc/plugin/PluginLoaderPatch; + public fun getIntegrationsClassDescriptor ()Ljava/lang/String; +} + public final class app/revanced/patches/duolingo/ad/DisableAdsPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/duolingo/ad/DisableAdsPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -960,6 +965,14 @@ public final class app/revanced/patches/shared/misc/mapping/ResourceMappingPatch public fun toString ()Ljava/lang/String; } +public abstract class app/revanced/patches/shared/misc/react/BaseReactPreloadScriptBootstrapperPatch : app/revanced/patcher/patch/BytecodePatch { + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZLjava/util/Set;Lkotlin/Pair;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZLjava/util/Set;Lkotlin/Pair;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V + public abstract fun getIntegrationsClassDescriptor ()Ljava/lang/String; +} + public abstract class app/revanced/patches/shared/misc/settings/BaseSettingsResourcePatch : app/revanced/patcher/patch/ResourcePatch, java/io/Closeable, java/util/Set, kotlin/jvm/internal/markers/KMutableSet { public fun ()V public fun (Lkotlin/Pair;Ljava/util/Set;)V diff --git a/src/main/kotlin/app/revanced/patches/discord/misc/plugin/PluginLoaderPatch.kt b/src/main/kotlin/app/revanced/patches/discord/misc/plugin/PluginLoaderPatch.kt new file mode 100644 index 0000000000..fe7c2d6ef7 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/discord/misc/plugin/PluginLoaderPatch.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.discord.misc.plugin + +import app.revanced.patches.discord.misc.plugin.fingerprints.MainActivityOnCreateFingerprint +import app.revanced.patches.shared.misc.react.BaseReactPreloadScriptBootstrapperPatch + +@Suppress("unused") +object PluginLoaderPatch : BaseReactPreloadScriptBootstrapperPatch( + name = "Plugin loader", + description = "Bootstraps a plugin loader.", + mainActivityOnCreateFingerprintInsertIndexPair = MainActivityOnCreateFingerprint to 2, +) { + override val integrationsClassDescriptor = "Lapp/revanced/integrations/discord/plugin/BunnyBootstrapperPatch;" +} diff --git a/src/main/kotlin/app/revanced/patches/discord/misc/plugin/fingerprints/MainActivityOnCreateFingerprint.kt b/src/main/kotlin/app/revanced/patches/discord/misc/plugin/fingerprints/MainActivityOnCreateFingerprint.kt new file mode 100644 index 0000000000..14e9f6a7bc --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/discord/misc/plugin/fingerprints/MainActivityOnCreateFingerprint.kt @@ -0,0 +1,7 @@ +package app.revanced.patches.discord.misc.plugin.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +internal object MainActivityOnCreateFingerprint : MethodFingerprint( + customFingerprint = { method, classDef -> method.name == "onCreate" && classDef.endsWith("ReactActivity;") }, +) diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/react/BaseReactPreloadScriptBootstrapperPatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/react/BaseReactPreloadScriptBootstrapperPatch.kt new file mode 100644 index 0000000000..e06e0117d2 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/misc/react/BaseReactPreloadScriptBootstrapperPatch.kt @@ -0,0 +1,63 @@ +package app.revanced.patches.shared.misc.react + +import app.revanced.patcher.PatchClass +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable +import app.revanced.patches.shared.misc.react.fingerprints.LoadScriptFromAssetsFingerprint +import app.revanced.patches.shared.misc.react.fingerprints.LoadScriptFromFileFingerprint +import app.revanced.util.resultOrThrow + +abstract class BaseReactPreloadScriptBootstrapperPatch( + name: String? = null, + description: String? = null, + compatiblePackages: Set? = null, + dependencies: Set? = null, + use: Boolean = true, + fingerprints: Set = emptySet(), + private val mainActivityOnCreateFingerprintInsertIndexPair: Pair, +) : BytecodePatch( + name = name, + description = description, + compatiblePackages = compatiblePackages, + dependencies = dependencies, + use = use, + requiresIntegrations = true, + fingerprints = setOf( + LoadScriptFromAssetsFingerprint, + LoadScriptFromFileFingerprint, + mainActivityOnCreateFingerprintInsertIndexPair.first, + ) + fingerprints, +) { + abstract val integrationsClassDescriptor: String + + override fun execute(context: BytecodeContext) { + val (mainActivityOnCreateFingerprint, insertIndex) = mainActivityOnCreateFingerprintInsertIndexPair + val loadScriptFromAssetMethod = LoadScriptFromAssetsFingerprint.resultOrThrow().mutableMethod + val (catalystInstanceImplClassDef, loadScriptFromFileMethod) = LoadScriptFromFileFingerprint.resultOrThrow() + .let { it.mutableClass to it.mutableMethod } + + // Create preload script on main activity creation. + mainActivityOnCreateFingerprint.resultOrThrow().mutableMethod.addInstructions( + insertIndex, // Skip super call. + "invoke-static { p0 }, " + + "$integrationsClassDescriptor->hookOnCreate(Landroid/app/Activity;)V", + ) + + // Copy of loadScriptFromFile method acts as a preload script loader. + loadScriptFromFileMethod.toMutable().apply { + name = "loadPreloadScriptFromFile" + }.let(catalystInstanceImplClassDef.methods::add) + + // Load preload script. + listOf(loadScriptFromFileMethod, loadScriptFromAssetMethod).forEach { loadScriptMethod -> + loadScriptMethod.addInstructions( + 0, + "invoke-static { v0 }, $integrationsClassDescriptor->" + + "hookLoadScriptFromFile($catalystInstanceImplClassDef)V", + ) + } + } +} diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/CatalystInstanceImplFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/CatalystInstanceImplFingerprint.kt new file mode 100644 index 0000000000..485d557dd5 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/CatalystInstanceImplFingerprint.kt @@ -0,0 +1,10 @@ +package app.revanced.patches.shared.misc.react.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +internal abstract class CatalystInstanceImplFingerprint(methodName: String) : + MethodFingerprint( + customFingerprint = { method, classDef -> + method.name == methodName && classDef.endsWith("CatalystInstanceImpl;") + }, + ) diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/LoadScriptFromAssetsFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/LoadScriptFromAssetsFingerprint.kt new file mode 100644 index 0000000000..91b2634837 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/LoadScriptFromAssetsFingerprint.kt @@ -0,0 +1,3 @@ +package app.revanced.patches.shared.misc.react.fingerprints + +internal object LoadScriptFromAssetsFingerprint : CatalystInstanceImplFingerprint("loadScriptFromAssets") diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/LoadScriptFromFileFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/LoadScriptFromFileFingerprint.kt new file mode 100644 index 0000000000..dfd656cbd8 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/misc/react/fingerprints/LoadScriptFromFileFingerprint.kt @@ -0,0 +1,3 @@ +package app.revanced.patches.shared.misc.react.fingerprints + +internal object LoadScriptFromFileFingerprint : CatalystInstanceImplFingerprint("loadScriptFromFile")