From 0383dc34a03e84f29bc2a7d56f2cf37d29c80e5b Mon Sep 17 00:00:00 2001 From: Temm Date: Wed, 13 Sep 2023 00:55:19 +0200 Subject: [PATCH 1/4] feat(tumblr): add hide tumblr live patch --- .../GetFeatureValueFingerprint.kt | 23 ++++ .../patch/FeatureOverridePatch.kt | 110 ++++++++++++++++++ .../fingerprints/LiveMarqueeFingerprint.kt | 6 + .../live/patch/DisableTumblrLivePatch.kt | 39 +++++++ 4 files changed, 178 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/tumblr/featureoverride/fingerprints/GetFeatureValueFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/tumblr/featureoverride/patch/FeatureOverridePatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/tumblr/live/fingerprints/LiveMarqueeFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/fingerprints/GetFeatureValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/fingerprints/GetFeatureValueFingerprint.kt new file mode 100644 index 0000000000..6a510b5625 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/fingerprints/GetFeatureValueFingerprint.kt @@ -0,0 +1,23 @@ +package app.revanced.patches.tumblr.featureoverride.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +// This fingerprint targets the method to get the value of a Feature in the class "com.tumblr.configuration.Feature" +// Features seem to be Tumblr's A/B testing program +// Feature states are loaded from the server in the "api-http2.tumblr.com/v2/config" request on (first) startup +// A lot of features are returned there, but most of them do not seem to do anything (anymore) +// They were likely removed in newer App versions to always be on, but are still returned +// as enabled for old App versions. +// Some features seem to be very old and never removed, though, such as Google Login +// The startIndex of the opcode pattern is at the start of the function after the arg null check, +// we want to insert our instructions there +object GetFeatureValueFingerprint : MethodFingerprint( + strings = listOf("feature"), + opcodes = listOf( + Opcode.IF_EQZ, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT + ), + customFingerprint = { method, _ -> method.definingClass == "Lcom/tumblr/configuration/Configuration;" } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/patch/FeatureOverridePatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/patch/FeatureOverridePatch.kt new file mode 100644 index 0000000000..432c6e5e35 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/patch/FeatureOverridePatch.kt @@ -0,0 +1,110 @@ +package app.revanced.patches.tumblr.featureoverride.patch + +import app.revanced.extensions.exception +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Package +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels +import app.revanced.patcher.extensions.or +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable +import app.revanced.patches.tumblr.featureoverride.fingerprints.GetFeatureValueFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation +import com.android.tools.smali.dexlib2.immutable.ImmutableMethod +import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter + +@Name("Feature Override") +@Description("Forcibly set the value of A/B testing features of your choice") +@Compatibility([Package("com.tumblr")]) +class FeatureOverridePatch : BytecodePatch( + listOf(GetFeatureValueFingerprint) +) { + override fun execute(context: BytecodeContext) = GetFeatureValueFingerprint.result?.let { + + // The method we want to inject into does not have enough registers, + // so instead of dealing with increasing the register count, we add a + // helper method "getValueOverride" to the class and pass it the feature object. + // If the helper returns null, we let the function run normally, otherwise we return the helper result value. + + val helperMethod = ImmutableMethod( + it.method.definingClass, + "getValueOverride", + listOf(ImmutableMethodParameter("Lcom/tumblr/configuration/Feature;", null, "feature")), + "Ljava/lang/String;", + AccessFlags.PUBLIC or AccessFlags.FINAL, + null, + null, + MutableMethodImplementation(4) + ).toMutable() + + // At the start of the helper, we get the String representation of the enum once. + // At the end of the helper, we return null. + // Between these two, we will later insert the checks & returns for the overrides + helperMethod.addInstructions( + 0, """ + # toString() the enum value + invoke-virtual {p1}, Lcom/tumblr/configuration/Feature;->toString()Ljava/lang/String; + move-result-object v0 + + # !!! If you add more instructions above this line, update helperInsertIndex below! + # Here we will insert one compare & return for every registered Feature override + # This is done below in the addOverride function + + # If none of the overrides returned a value, we should return null + const/4 v0, 0x0 + return-object v0 + """ + ) + // This is where we insert the override code. Should we not hardcode this? Fingerprinting it seems silly. + val helperInsertIndex = 2 + + it.mutableClass.methods.add(helperMethod) + + // Here we actually insert the hook to call our helper method and return its value if it returns not null + val getFeatureIndex = it.scanResult.patternScanResult!!.startIndex + it.mutableMethod.addInstructionsWithLabels( + getFeatureIndex, """ + # Call the Helper Method with the Feature + invoke-virtual {p0, p1}, Lcom/tumblr/configuration/Configuration;->getValueOverride(Lcom/tumblr/configuration/Feature;)Ljava/lang/String; + move-result-object v0 + # If it returned null, skip + if-eqz v0, :is_null + # If it didnt return null, return that string + return-object v0 + + # If our override helper returned null, we let the function continue normally + :is_null + nop + """ + ) + addOverride = { name, value -> + // For every added override, we add a few instructions in the middle of the helper method + // to check if the feature is the one we want and return the override value if it is. + helperMethod.addInstructionsWithLabels( + helperInsertIndex, """ + # v0 is still the string name of the currently checked feature from above + # Compare the current string with the override string + const-string v1, "$name" + invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z + move-result v1 + # If the current string is the one we want to override, we return the override value + if-eqz v1, :no_override + const-string v1, "$value" + return-object v1 + # Else we just continue... + :no_override + nop + """ + ) + } + } ?: throw GetFeatureValueFingerprint.exception + + companion object { + internal lateinit var addOverride: (String, String) -> Unit + private set + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tumblr/live/fingerprints/LiveMarqueeFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/live/fingerprints/LiveMarqueeFingerprint.kt new file mode 100644 index 0000000000..3f4da4b004 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tumblr/live/fingerprints/LiveMarqueeFingerprint.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.tumblr.live.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint + +// This works identically to the Tumblr AdWaterfallFingerprint, see comments there +object LiveMarqueeFingerprint : MethodFingerprint(strings = listOf("live_marquee")) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt new file mode 100644 index 0000000000..e5da39c4f9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt @@ -0,0 +1,39 @@ +package app.revanced.patches.tumblr.live.patch + +import app.revanced.extensions.exception +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Package +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patches.tumblr.featureoverride.patch.FeatureOverridePatch +import app.revanced.patches.tumblr.live.fingerprints.LiveMarqueeFingerprint +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch +@Name("Disable Tumblr Live") +@Description("Disable the Tumblr Live tab button and dashboard carousel") +@DependsOn([FeatureOverridePatch::class]) +@Compatibility([Package("com.tumblr")]) +class DisableTumblrLivePatch : BytecodePatch( + listOf(LiveMarqueeFingerprint) +) { + override fun execute(context: BytecodeContext) = LiveMarqueeFingerprint.result?.let { + it.scanResult.stringsScanResult!!.matches.forEach { match -> + // Just like with the DisableDashboardAdsPatch, we replace the string constant "live_marquee" + // with a dummy so the app doesn't recognize this type of element in the Dashboard and skips it + val stringRegister = it.mutableMethod.getInstruction(match.index).registerA + it.mutableMethod.replaceInstruction( + match.index, "const-string v$stringRegister, \"dummy2\"" + ) + } + + // We hide the Tab button for Tumblr Live by forcing the feature flag to false + FeatureOverridePatch.addOverride("liveStreaming", "false") + } ?: throw LiveMarqueeFingerprint.exception +} \ No newline at end of file From 7d987c77b82ef9bf6752bf9fcf1b027c58ebc17c Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 14 Sep 2023 03:01:01 +0200 Subject: [PATCH 2/4] refactor: Small refactoring --- .../GetFeatureValueFingerprint.kt | 16 +++--- .../patch/OverrideFeatureFlagsPatch.kt} | 52 +++++++++++-------- .../live/patch/DisableTumblrLivePatch.kt | 19 +++---- 3 files changed, 48 insertions(+), 39 deletions(-) rename src/main/kotlin/app/revanced/patches/tumblr/{featureoverride => featureflags}/fingerprints/GetFeatureValueFingerprint.kt (71%) rename src/main/kotlin/app/revanced/patches/tumblr/{featureoverride/patch/FeatureOverridePatch.kt => featureflags/patch/OverrideFeatureFlagsPatch.kt} (80%) diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/fingerprints/GetFeatureValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt similarity index 71% rename from src/main/kotlin/app/revanced/patches/tumblr/featureoverride/fingerprints/GetFeatureValueFingerprint.kt rename to src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt index 6a510b5625..1507b5ddc2 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/fingerprints/GetFeatureValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt @@ -1,17 +1,17 @@ -package app.revanced.patches.tumblr.featureoverride.fingerprints +package app.revanced.patches.tumblr.featureflags.fingerprints import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode -// This fingerprint targets the method to get the value of a Feature in the class "com.tumblr.configuration.Feature" -// Features seem to be Tumblr's A/B testing program -// Feature states are loaded from the server in the "api-http2.tumblr.com/v2/config" request on (first) startup -// A lot of features are returned there, but most of them do not seem to do anything (anymore) +// This fingerprint targets the method to get the value of a Feature in the class "com.tumblr.configuration.Feature". +// Features seem to be Tumblr's A/B testing program. +// Feature states are loaded from the server in the "api-http2.tumblr.com/v2/config" request on (first) startup. +// A lot of features are returned there, but most of them do not seem to do anything (anymore). // They were likely removed in newer App versions to always be on, but are still returned // as enabled for old App versions. -// Some features seem to be very old and never removed, though, such as Google Login -// The startIndex of the opcode pattern is at the start of the function after the arg null check, -// we want to insert our instructions there +// Some features seem to be very old and never removed, though, such as Google Login. +// The startIndex of the opcode pattern is at the start of the function after the arg null check. +// we want to insert our instructions there. object GetFeatureValueFingerprint : MethodFingerprint( strings = listOf("feature"), opcodes = listOf( diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/patch/FeatureOverridePatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt similarity index 80% rename from src/main/kotlin/app/revanced/patches/tumblr/featureoverride/patch/FeatureOverridePatch.kt rename to src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt index 432c6e5e35..7ea2808840 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/featureoverride/patch/FeatureOverridePatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.tumblr.featureoverride.patch +package app.revanced.patches.tumblr.featureflags.patch import app.revanced.extensions.exception import app.revanced.patcher.annotation.Compatibility @@ -11,25 +11,23 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.or import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable -import app.revanced.patches.tumblr.featureoverride.fingerprints.GetFeatureValueFingerprint +import app.revanced.patches.tumblr.featureflags.fingerprints.GetFeatureValueFingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter -@Name("Feature Override") -@Description("Forcibly set the value of A/B testing features of your choice") +@Name("Override feature flags") +@Description("Forcibly set the value of A/B testing features of your choice.") @Compatibility([Package("com.tumblr")]) -class FeatureOverridePatch : BytecodePatch( +class OverrideFeatureFlagsPatch : BytecodePatch( listOf(GetFeatureValueFingerprint) ) { override fun execute(context: BytecodeContext) = GetFeatureValueFingerprint.result?.let { - // The method we want to inject into does not have enough registers, // so instead of dealing with increasing the register count, we add a // helper method "getValueOverride" to the class and pass it the feature object. // If the helper returns null, we let the function run normally, otherwise we return the helper result value. - val helperMethod = ImmutableMethod( it.method.definingClass, "getValueOverride", @@ -39,13 +37,13 @@ class FeatureOverridePatch : BytecodePatch( null, null, MutableMethodImplementation(4) - ).toMutable() - - // At the start of the helper, we get the String representation of the enum once. - // At the end of the helper, we return null. - // Between these two, we will later insert the checks & returns for the overrides - helperMethod.addInstructions( - 0, """ + ).toMutable().apply { + // At the start of the helper, we get the String representation of the enum once. + // At the end of the helper, we return null. + // Between these two, we will later insert the checks & returns for the overrides + addInstructions( + 0, + """ # toString() the enum value invoke-virtual {p1}, Lcom/tumblr/configuration/Feature;->toString()Ljava/lang/String; move-result-object v0 @@ -58,16 +56,17 @@ class FeatureOverridePatch : BytecodePatch( const/4 v0, 0x0 return-object v0 """ - ) - // This is where we insert the override code. Should we not hardcode this? Fingerprinting it seems silly. - val helperInsertIndex = 2 + ) + }.also { helperMethod -> + it.mutableClass.methods.add(helperMethod) + } - it.mutableClass.methods.add(helperMethod) // Here we actually insert the hook to call our helper method and return its value if it returns not null val getFeatureIndex = it.scanResult.patternScanResult!!.startIndex it.mutableMethod.addInstructionsWithLabels( - getFeatureIndex, """ + getFeatureIndex, + """ # Call the Helper Method with the Feature invoke-virtual {p0, p1}, Lcom/tumblr/configuration/Configuration;->getValueOverride(Lcom/tumblr/configuration/Feature;)Ljava/lang/String; move-result-object v0 @@ -81,11 +80,14 @@ class FeatureOverridePatch : BytecodePatch( nop """ ) + + val helperInsertIndex = 2 addOverride = { name, value -> // For every added override, we add a few instructions in the middle of the helper method // to check if the feature is the one we want and return the override value if it is. helperMethod.addInstructionsWithLabels( - helperInsertIndex, """ + helperInsertIndex, + """ # v0 is still the string name of the currently checked feature from above # Compare the current string with the override string const-string v1, "$name" @@ -104,7 +106,13 @@ class FeatureOverridePatch : BytecodePatch( } ?: throw GetFeatureValueFingerprint.exception companion object { - internal lateinit var addOverride: (String, String) -> Unit - private set + /** + * Override a feature flag with a value. + * + * @param name The name of the feature flag to override. + * @param value The value to override the feature flag with. + */ + @Suppress("KDocUnresolvedReference") + internal lateinit var addOverride: (name: String, value: String) -> Unit private set } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt index e5da39c4f9..f09856e481 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt @@ -11,29 +11,30 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.tumblr.featureoverride.patch.FeatureOverridePatch +import app.revanced.patches.tumblr.featureflags.patch.OverrideFeatureFlagsPatch import app.revanced.patches.tumblr.live.fingerprints.LiveMarqueeFingerprint import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch @Name("Disable Tumblr Live") -@Description("Disable the Tumblr Live tab button and dashboard carousel") -@DependsOn([FeatureOverridePatch::class]) +@Description("Disable the Tumblr Live tab button and dashboard carousel.") +@DependsOn([OverrideFeatureFlagsPatch::class]) @Compatibility([Package("com.tumblr")]) class DisableTumblrLivePatch : BytecodePatch( listOf(LiveMarqueeFingerprint) ) { override fun execute(context: BytecodeContext) = LiveMarqueeFingerprint.result?.let { it.scanResult.stringsScanResult!!.matches.forEach { match -> - // Just like with the DisableDashboardAdsPatch, we replace the string constant "live_marquee" + // Replace the string constant "live_marquee" // with a dummy so the app doesn't recognize this type of element in the Dashboard and skips it - val stringRegister = it.mutableMethod.getInstruction(match.index).registerA - it.mutableMethod.replaceInstruction( - match.index, "const-string v$stringRegister, \"dummy2\"" - ) + it.mutableMethod.apply { + val stringRegister = getInstruction(match.index).registerA + replaceInstruction(match.index, "const-string v$stringRegister, \"dummy2\"") + } + } // We hide the Tab button for Tumblr Live by forcing the feature flag to false - FeatureOverridePatch.addOverride("liveStreaming", "false") + OverrideFeatureFlagsPatch.addOverride("liveStreaming", "false") } ?: throw LiveMarqueeFingerprint.exception } \ No newline at end of file From b716820c9a1e1b3f913b65dd10d30c2c83ec8d77 Mon Sep 17 00:00:00 2001 From: Temm Date: Thu, 14 Sep 2023 19:29:00 +0200 Subject: [PATCH 3/4] refactor(tumblr): improve feature flags patch comments --- .../patch/OverrideFeatureFlagsPatch.kt | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt index 7ea2808840..e2ebfe1b2a 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt @@ -24,10 +24,10 @@ class OverrideFeatureFlagsPatch : BytecodePatch( listOf(GetFeatureValueFingerprint) ) { override fun execute(context: BytecodeContext) = GetFeatureValueFingerprint.result?.let { - // The method we want to inject into does not have enough registers, - // so instead of dealing with increasing the register count, we add a - // helper method "getValueOverride" to the class and pass it the feature object. - // If the helper returns null, we let the function run normally, otherwise we return the helper result value. + // The method we want to inject into does not have enough registers, so we inject a helper method + // and inject more instructions into it later, see addOverride. + // This is not in an integration since the unused variable would get compiled away and the method would + // get compiled to only have one register, which is not enough for our later injected instructions. val helperMethod = ImmutableMethod( it.method.definingClass, "getValueOverride", @@ -38,9 +38,10 @@ class OverrideFeatureFlagsPatch : BytecodePatch( null, MutableMethodImplementation(4) ).toMutable().apply { - // At the start of the helper, we get the String representation of the enum once. - // At the end of the helper, we return null. - // Between these two, we will later insert the checks & returns for the overrides + // This is the equivalent of + // String featureName = feature.toString() + // + // return null addInstructions( 0, """ @@ -61,8 +62,10 @@ class OverrideFeatureFlagsPatch : BytecodePatch( it.mutableClass.methods.add(helperMethod) } - // Here we actually insert the hook to call our helper method and return its value if it returns not null + // This is equivalent to + // String forcedValue = getValueOverride(feature) + // if (forcedValue != null) return forcedValue val getFeatureIndex = it.scanResult.patternScanResult!!.startIndex it.mutableMethod.addInstructionsWithLabels( getFeatureIndex, @@ -85,6 +88,8 @@ class OverrideFeatureFlagsPatch : BytecodePatch( addOverride = { name, value -> // For every added override, we add a few instructions in the middle of the helper method // to check if the feature is the one we want and return the override value if it is. + // This is equivalent to + // if (featureName == {name}) return {value} helperMethod.addInstructionsWithLabels( helperInsertIndex, """ From e22c4a77bf37932ab44066e5a06378c1fd3eed09 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 20 Sep 2023 18:07:00 +0200 Subject: [PATCH 4/4] fix usage --- .../DisableBlogNotificationReminderPatch.kt | 2 +- .../DisableGiftMessagePopupPatch.kt | 2 +- .../{patch => }/OverrideFeatureFlagsPatch.kt | 35 ++++++++----------- .../{patch => }/DisableTumblrLivePatch.kt | 29 +++++++-------- 4 files changed, 29 insertions(+), 39 deletions(-) rename src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/{patch => }/DisableBlogNotificationReminderPatch.kt (94%) rename src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/{patch => }/DisableGiftMessagePopupPatch.kt (94%) rename src/main/kotlin/app/revanced/patches/tumblr/featureflags/{patch => }/OverrideFeatureFlagsPatch.kt (85%) rename src/main/kotlin/app/revanced/patches/tumblr/live/{patch => }/DisableTumblrLivePatch.kt (63%) diff --git a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/patch/DisableBlogNotificationReminderPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/DisableBlogNotificationReminderPatch.kt similarity index 94% rename from src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/patch/DisableBlogNotificationReminderPatch.kt rename to src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/DisableBlogNotificationReminderPatch.kt index 5003a37270..e073da5f15 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/patch/DisableBlogNotificationReminderPatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/notifications/DisableBlogNotificationReminderPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.tumblr.annoyances.notifications.patch +package app.revanced.patches.tumblr.annoyances.notifications import app.revanced.extensions.exception import app.revanced.patcher.data.BytecodeContext diff --git a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/patch/DisableGiftMessagePopupPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/DisableGiftMessagePopupPatch.kt similarity index 94% rename from src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/patch/DisableGiftMessagePopupPatch.kt rename to src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/DisableGiftMessagePopupPatch.kt index f93597ca15..17c15a792f 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/patch/DisableGiftMessagePopupPatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/DisableGiftMessagePopupPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.tumblr.annoyances.popups.patch +package app.revanced.patches.tumblr.annoyances.popups import app.revanced.extensions.exception import app.revanced.patcher.data.BytecodeContext diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt similarity index 85% rename from src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt rename to src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt index e2ebfe1b2a..77202534d7 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/patch/OverrideFeatureFlagsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt @@ -1,15 +1,12 @@ -package app.revanced.patches.tumblr.featureflags.patch +package app.revanced.patches.tumblr.featureflags import app.revanced.extensions.exception -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Package import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.or import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patches.tumblr.featureflags.fingerprints.GetFeatureValueFingerprint import com.android.tools.smali.dexlib2.AccessFlags @@ -17,12 +14,19 @@ import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter -@Name("Override feature flags") -@Description("Forcibly set the value of A/B testing features of your choice.") -@Compatibility([Package("com.tumblr")]) -class OverrideFeatureFlagsPatch : BytecodePatch( - listOf(GetFeatureValueFingerprint) +@Patch(description = "Forcibly set the value of A/B testing features of your choice.") +object OverrideFeatureFlagsPatch : BytecodePatch( + setOf(GetFeatureValueFingerprint) ) { + /** + * Override a feature flag with a value. + * + * @param name The name of the feature flag to override. + * @param value The value to override the feature flag with. + */ + @Suppress("KDocUnresolvedReference") + internal lateinit var addOverride: (name: String, value: String) -> Unit private set + override fun execute(context: BytecodeContext) = GetFeatureValueFingerprint.result?.let { // The method we want to inject into does not have enough registers, so we inject a helper method // and inject more instructions into it later, see addOverride. @@ -109,15 +113,4 @@ class OverrideFeatureFlagsPatch : BytecodePatch( ) } } ?: throw GetFeatureValueFingerprint.exception - - companion object { - /** - * Override a feature flag with a value. - * - * @param name The name of the feature flag to override. - * @param value The value to override the feature flag with. - */ - @Suppress("KDocUnresolvedReference") - internal lateinit var addOverride: (name: String, value: String) -> Unit private set - } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt similarity index 63% rename from src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt rename to src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt index f09856e481..f588d02a25 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/live/patch/DisableTumblrLivePatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt @@ -1,27 +1,25 @@ -package app.revanced.patches.tumblr.live.patch +package app.revanced.patches.tumblr.live import app.revanced.extensions.exception -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Package import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.tumblr.featureflags.patch.OverrideFeatureFlagsPatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch import app.revanced.patches.tumblr.live.fingerprints.LiveMarqueeFingerprint import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -@Patch -@Name("Disable Tumblr Live") -@Description("Disable the Tumblr Live tab button and dashboard carousel.") -@DependsOn([OverrideFeatureFlagsPatch::class]) -@Compatibility([Package("com.tumblr")]) -class DisableTumblrLivePatch : BytecodePatch( - listOf(LiveMarqueeFingerprint) +@Patch( + name = "Disable Tumblr Live", + description = "Disable the Tumblr Live tab button and dashboard carousel.", + dependencies = [OverrideFeatureFlagsPatch::class], + compatiblePackages = [CompatiblePackage("com.tumblr")] +) +@Suppress("unused") +object DisableTumblrLivePatch : BytecodePatch( + setOf(LiveMarqueeFingerprint) ) { override fun execute(context: BytecodeContext) = LiveMarqueeFingerprint.result?.let { it.scanResult.stringsScanResult!!.matches.forEach { match -> @@ -31,7 +29,6 @@ class DisableTumblrLivePatch : BytecodePatch( val stringRegister = getInstruction(match.index).registerA replaceInstruction(match.index, "const-string v$stringRegister, \"dummy2\"") } - } // We hide the Tab button for Tumblr Live by forcing the feature flag to false