Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Discord): Add Plugin loader patch #3632

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions api/revanced-patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZLjava/util/Set;Lkotlin/Pair;)V
public synthetic fun <init> (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 <init> ()V
public fun <init> (Lkotlin/Pair;Ljava/util/Set;)V
Expand Down
Original file line number Diff line number Diff line change
@@ -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;"
}
Original file line number Diff line number Diff line change
@@ -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;") },
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
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.extensions.InstructionExtensions.getInstructions
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
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod

abstract class BaseReactPreloadScriptBootstrapperPatch(
name: String? = null,
description: String? = null,
compatiblePackages: Set<CompatiblePackage>? = null,
dependencies: Set<PatchClass>? = null,
use: Boolean = true,
fingerprints: Set<MethodFingerprint> = emptySet(),
private val mainActivityOnCreateFingerprintInsertIndexPair: Pair<MethodFingerprint, Int>,
) : 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.
catalystInstanceImplClassDef.methods.add(
ImmutableMethod(
loadScriptFromFileMethod.definingClass,
"loadPreloadScriptFromFile",
loadScriptFromFileMethod.parameters,
loadScriptFromFileMethod.returnType,
loadScriptFromFileMethod.accessFlags,
null,
null,
MutableMethodImplementation(4),
).toMutable().apply {
// Copy list as the reference is modified below.
addInstructions(loadScriptFromFileMethod.getInstructions().toList())
},
)

// Load preload script.
listOf(loadScriptFromFileMethod, loadScriptFromAssetMethod).forEach { loadScriptMethod ->
loadScriptMethod.addInstructions(
0,
"invoke-static { v0 }, $integrationsClassDescriptor->" +
"hookLoadScriptFromFile($catalystInstanceImplClassDef)V",
)
}
}
}
Original file line number Diff line number Diff line change
@@ -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;")
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package app.revanced.patches.shared.misc.react.fingerprints

internal object LoadScriptFromAssetsFingerprint : CatalystInstanceImplFingerprint("loadScriptFromAssets")
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package app.revanced.patches.shared.misc.react.fingerprints

internal object LoadScriptFromFileFingerprint : CatalystInstanceImplFingerprint("loadScriptFromFile")
Loading