diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt index 1fd49a59..f81d856f 100644 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt @@ -2,13 +2,13 @@ package app.revanced.patches.tiktok.misc.integrations.fingerprints import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patches.tiktok.misc.integrations.annotations.TikTokIntegrationsCompatibility +import app.revanced.shared.patches.AbstractIntegrationsPatch.IntegrationsFingerprint @Name("init-fingerprint") @TikTokIntegrationsCompatibility @Version("0.0.1") -object InitFingerprint : MethodFingerprint( +object InitFingerprint : IntegrationsFingerprint( customFingerprint = { methodDef -> methodDef.definingClass.endsWith("/AwemeHostApplication;") && methodDef.name == "onCreate" diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt index 79780d1d..2b3a8263 100644 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt @@ -1,38 +1,13 @@ package app.revanced.patches.tiktok.misc.integrations.patch -import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patches.tiktok.misc.integrations.annotations.TikTokIntegrationsCompatibility import app.revanced.patches.tiktok.misc.integrations.fingerprints.InitFingerprint +import app.revanced.shared.patches.AbstractIntegrationsPatch @Name("tiktok-integrations") -@Description("Applies mandatory patches to implement the ReVanced integrations into the application.") @TikTokIntegrationsCompatibility -@Version("0.0.1") -class TikTokIntegrationsPatch : BytecodePatch( - listOf( - InitFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - if (context.findClass("Lapp/revanced/tiktok/utils/ReVancedUtils") == null) - return PatchResultError("Integrations have not been merged yet. This patch can not succeed without the integrations.") - val result = InitFingerprint.result!! - - val method = result.mutableMethod - val implementation = method.implementation!! - val count = implementation.registerCount - 1 - - method.addInstruction( - 0, "sput-object v$count, Lapp/revanced/tiktok/utils/ReVancedUtils;->context:Landroid/content/Context;" - ) - return PatchResultSuccess() - } -} \ No newline at end of file +class TikTokIntegrationsPatch : AbstractIntegrationsPatch( + "Lapp/revanced/tiktok/utils/ReVancedUtils;", + listOf(InitFingerprint) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt index 66b874de..ba2aaa5b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt @@ -2,12 +2,12 @@ package app.revanced.patches.youtube.misc.integrations.fingerprints import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility +import app.revanced.shared.patches.AbstractIntegrationsPatch.IntegrationsFingerprint @Name("init-fingerprint") @IntegrationsCompatibility @Version("0.0.1") -object InitFingerprint : MethodFingerprint( - strings = listOf("Application creation") +object InitFingerprint : IntegrationsFingerprint( + strings = listOf("Application creation"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt index 0d1312be..2333e4e8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt @@ -2,12 +2,13 @@ package app.revanced.patches.youtube.misc.integrations.fingerprints import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility +import app.revanced.shared.patches.AbstractIntegrationsPatch.IntegrationsFingerprint @Name("service-fingerprint") @IntegrationsCompatibility @Version("0.0.1") -object ServiceFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> methodDef.definingClass.endsWith("ApiPlayerService;") && methodDef.name == "" } +object ServiceFingerprint : IntegrationsFingerprint( + customFingerprint = { methodDef -> methodDef.definingClass.endsWith("ApiPlayerService;") && methodDef.name == "" }, + contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt index 5bd664de..efe7dd3e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt @@ -2,15 +2,15 @@ package app.revanced.patches.youtube.misc.integrations.fingerprints import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility +import app.revanced.shared.patches.AbstractIntegrationsPatch.IntegrationsFingerprint @Name("standalone-player-fingerprint") @IntegrationsCompatibility @Version("0.0.1") -object StandalonePlayerFingerprint : MethodFingerprint( +object StandalonePlayerFingerprint : IntegrationsFingerprint( strings = listOf( "Invalid PlaybackStartDescriptor. Returning the instance itself.", "com.google.android.music", - ) + ), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt index f7eaff30..cd698632 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt @@ -1,59 +1,15 @@ package app.revanced.patches.youtube.misc.integrations.patch -import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.MethodFingerprintExtensions.name -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.or -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable -import app.revanced.patcher.util.smali.toInstructions import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility import app.revanced.patches.youtube.misc.integrations.fingerprints.InitFingerprint import app.revanced.patches.youtube.misc.integrations.fingerprints.ServiceFingerprint import app.revanced.patches.youtube.misc.integrations.fingerprints.StandalonePlayerFingerprint -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.immutable.ImmutableMethod -import org.jf.dexlib2.immutable.ImmutableMethodImplementation +import app.revanced.shared.patches.AbstractIntegrationsPatch @Name("integrations") -@Description("Applies mandatory patches to implement the ReVanced integrations into the application.") @IntegrationsCompatibility -@Version("0.0.1") -class IntegrationsPatch : BytecodePatch( - listOf( - InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint - ) -) { - companion object { - private const val INTEGRATIONS_DESCRIPTOR = "Lapp/revanced/integrations/utils/ReVancedUtils;" - } - - override fun execute(context: BytecodeContext): PatchResult { - if (context.findClass(INTEGRATIONS_DESCRIPTOR) == null) - return PatchResultError("Integrations have not been merged yet. This patch can not succeed without merging the integrations.") - - arrayOf(InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint).map { - it to (it.result ?: return PatchResultError("${it.name} failed to resolve")) - }.forEach { (fingerprint, result) -> - with(result.mutableMethod) { - // parameter which holds the context - val contextParameter = if (fingerprint == ServiceFingerprint) parameters.size else 1 - // register which holds the context - val contextRegister = implementation!!.registerCount - contextParameter - - addInstruction( - 0, - "sput-object v$contextRegister, $INTEGRATIONS_DESCRIPTOR->context:Landroid/content/Context;" - ) - } - } - - return PatchResultSuccess() - } -} \ No newline at end of file +class IntegrationsPatch : AbstractIntegrationsPatch( + "Lapp/revanced/integrations/utils/ReVancedUtils;", + listOf(InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint), +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/shared/patches/IntegrationsFingerprint.kt b/src/main/kotlin/app/revanced/shared/patches/IntegrationsFingerprint.kt new file mode 100644 index 00000000..1673f4c0 --- /dev/null +++ b/src/main/kotlin/app/revanced/shared/patches/IntegrationsFingerprint.kt @@ -0,0 +1,67 @@ +package app.revanced.shared.patches + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultError +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.shared.patches.AbstractIntegrationsPatch.IntegrationsFingerprint.RegisterResolver +import org.jf.dexlib2.iface.Method + +@Description("Applies mandatory patches to implement the ReVanced integrations into the application.") +@Version("0.0.1") +abstract class AbstractIntegrationsPatch( + private val integrationsDescriptor: String, + private val hooks: Iterable +) : BytecodePatch(hooks) { + /** + * [MethodFingerprint] for integrations. + * + * @param contextRegisterResolver A [RegisterResolver] to get the register. + * @see MethodFingerprint + */ + abstract class IntegrationsFingerprint( + strings: Iterable? = null, + customFingerprint: ((methodDef: Method) -> Boolean)? = null, + private val contextRegisterResolver: (Method) -> Int = object : RegisterResolver {} + ) : MethodFingerprint(strings = strings, customFingerprint = customFingerprint) { + fun invoke(integrationsDescriptor: String): PatchResult { + result?.mutableMethod?.let { method -> + val contextRegister = contextRegisterResolver(method) + + method.addInstruction( + 0, + "sput-object v$contextRegister, " + + "$integrationsDescriptor->context:Landroid/content/Context;" + ) + } ?: return PatchResultError("Could not find hook target fingerprint.") + + return PatchResultSuccess() + } + + interface RegisterResolver : (Method) -> Int { + override operator fun invoke(method: Method) = method.implementation!!.registerCount - 1 + } + } + + override fun execute(context: BytecodeContext): PatchResult { + if (context.findClass(integrationsDescriptor) == null) return MISSING_INTEGRATIONS + + for (hook in hooks) hook.invoke(integrationsDescriptor).let { + if (it is PatchResultError) return it + } + + return PatchResultSuccess() + } + + private companion object { + val MISSING_INTEGRATIONS = PatchResultError( + "Integrations have not been merged yet. " + + "This patch can not succeed without merging the integrations." + ) + } +} \ No newline at end of file