fixes of errors made by AI

This commit is contained in:
oSumAtrIX 2026-01-26 15:07:17 +01:00
parent 7302d29383
commit b6975fe015
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
28 changed files with 183 additions and 189 deletions

View file

@ -1,4 +1,3 @@
package app.revanced.patches.instagram.hide.navigation package app.revanced.patches.instagram.hide.navigation
import app.revanced.patcher.* import app.revanced.patcher.*
@ -11,6 +10,9 @@ internal val BytecodePatchContext.initializeNavigationButtonsListMethod by getti
returnType("Ljava/util/List;") returnType("Ljava/util/List;")
} }
internal val navigationButtonsEnumClassDefMatch = firstMethodComposite( internal val BytecodePatchContext.navigationButtonsEnumMethod by gettingFirstMethodDeclaratively(
"FEED", "fragment_feed", "SEARCH", "fragment_search", "FEED",
"fragment_feed",
"SEARCH",
"fragment_search",
) )

View file

@ -2,6 +2,7 @@ package app.revanced.patches.instagram.hide.navigation
import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.firstMutableMethodDeclaratively import app.revanced.patcher.firstMutableMethodDeclaratively
import app.revanced.patcher.immutableClassDef
import app.revanced.patcher.name import app.revanced.patcher.name
import app.revanced.patcher.patch.booleanOption import app.revanced.patcher.patch.booleanOption
import app.revanced.patcher.patch.creatingBytecodePatch import app.revanced.patcher.patch.creatingBytecodePatch
@ -73,7 +74,7 @@ val `Hide navigation buttons` by creatingBytecodePatch(
// Get the field name which contains the name of the enum for the navigation button // Get the field name which contains the name of the enum for the navigation button
// ("fragment_clips", "fragment_share", ...) // ("fragment_clips", "fragment_share", ...)
val enumNameField = navigationButtonsEnumClassDefMatch.classDef.firstMutableMethodDeclaratively { val enumNameField = navigationButtonsEnumMethod.immutableClassDef.firstMutableMethodDeclaratively {
name("<init>") name("<init>")
}.let { method -> }.let { method ->
method.indexOfFirstInstructionOrThrow { method.indexOfFirstInstructionOrThrow {

View file

@ -1,13 +1,11 @@
package app.revanced.patches.instagram.misc.devmenu package app.revanced.patches.instagram.misc.devmenu
import app.revanced.patcher.extensions.methodReference
import app.revanced.patcher.patch.creatingBytecodePatch import app.revanced.patcher.patch.creatingBytecodePatch
import app.revanced.util.Utils.trimIndentMultiline import app.revanced.util.Utils.trimIndentMultiline
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.indexOfFirstStringInstruction
import app.revanced.util.returnEarly import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Suppress("unused", "ObjectPropertyName") @Suppress("unused", "ObjectPropertyName")
val `Enable developer menu` by creatingBytecodePatch( val `Enable developer menu` by creatingBytecodePatch(
@ -21,16 +19,17 @@ val `Enable developer menu` by creatingBytecodePatch(
compatibleWith("com.instagram.android") compatibleWith("com.instagram.android")
apply { apply {
clearNotificationReceiverMethod.apply { clearNotificationReceiverMethodMatch.let {
val stringIndex = indexOfFirstStringInstruction("NOTIFICATION_DISMISSED") val stringIndex = it.indices.first()
indexOfFirstInstructionReversedOrThrow(stringIndex) {
val reference = getReference<MethodReference>() it.method.indexOfFirstInstructionReversedOrThrow(stringIndex) {
val reference = methodReference
opcode in listOf(Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC_RANGE) && opcode in listOf(Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC_RANGE) &&
reference?.parameterTypes?.size == 1 && reference?.parameterTypes?.size == 1 &&
reference.parameterTypes.first() == "Lcom/instagram/common/session/UserSession;" && reference.parameterTypes.first() == "Lcom/instagram/common/session/UserSession;" &&
reference.returnType == "Z" reference.returnType == "Z"
}.let { index -> }.let { index ->
navigate(this).to(index).stop().returnEarly(true) navigate(it.method).to(index).stop().returnEarly(true)
} }
} }
} }

View file

@ -1,11 +1,9 @@
package app.revanced.patches.instagram.misc.devmenu package app.revanced.patches.instagram.misc.devmenu
import app.revanced.patcher.* import app.revanced.patcher.*
import app.revanced.patcher.patch.BytecodePatchContext
internal val BytecodePatchContext.clearNotificationReceiverMethod by gettingFirstMutableMethodDeclaratively( internal val clearNotificationReceiverMethodMatch = firstMethodComposite {
"NOTIFICATION_DISMISSED",
) {
name("onReceive") name("onReceive")
definingClass("Lcom/instagram/notifications/push/ClearNotificationReceiver;") definingClass("Lcom/instagram/notifications/push/ClearNotificationReceiver;")
instructions("NOTIFICATION_DISMISSED"())
} }

View file

@ -7,7 +7,7 @@ import app.revanced.patcher.returnType
internal const val TARGET_STRING = "Tracking.ARG_CLICK_SOURCE" internal const val TARGET_STRING = "Tracking.ARG_CLICK_SOURCE"
internal val inAppBrowserFunctionMethodMatch = firstMethodComposite { internal val inAppBrowserFunctionMethodMatch = firstMethodComposite("TrackingInfo.ARG_MODULE_NAME") {
instructions("TrackingInfo.ARG_MODULE_NAME"(), TARGET_STRING()) instructions(TARGET_STRING())
returnType("Z") returnType("Z")
} }

View file

@ -21,25 +21,27 @@ val `Open links externally` by creatingBytecodePatch(
compatibleWith("com.instagram.android") compatibleWith("com.instagram.android")
apply { apply {
inAppBrowserFunctionMethodMatch.method.apply { inAppBrowserFunctionMethodMatch.let {
val stringMatchIndex = inAppBrowserFunctionMethodMatch.indices.first() val stringMatchIndex = it.indices.first()
val urlResultObjIndex = indexOfFirstInstructionOrThrow( it.method.apply {
stringMatchIndex, val urlResultObjIndex = indexOfFirstInstructionOrThrow(
Opcode.MOVE_OBJECT_FROM16, stringMatchIndex,
) Opcode.MOVE_OBJECT_FROM16,
)
// Register that contains the url after moving from a higher register. // Register that contains the url after moving from a higher register.
val urlRegister = getInstruction<TwoRegisterInstruction>(urlResultObjIndex).registerA val urlRegister = getInstruction<TwoRegisterInstruction>(urlResultObjIndex).registerA
addInstructions( addInstructions(
urlResultObjIndex + 1, urlResultObjIndex + 1,
""" """
invoke-static { v$urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->openExternally(Ljava/lang/String;)Z invoke-static { v$urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->openExternally(Ljava/lang/String;)Z
move-result v$urlRegister move-result v$urlRegister
return v$urlRegister return v$urlRegister
""", """,
) )
}
} }
} }
} }

View file

@ -3,24 +3,22 @@ package app.revanced.patches.instagram.misc.share
import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstStringInstruction
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.mutable.MutableMethod import com.android.tools.smali.dexlib2.mutable.MutableMethod
context(_: BytecodePatchContext) internal fun BytecodePatchContext.editShareLinksPatch(block: MutableMethod.(index: Int, register: Int) -> Unit) {
internal fun editShareLinksPatch(block: MutableMethod.(index: Int, register: Int) -> Unit) {
val methodsToPatch = arrayOf( val methodsToPatch = arrayOf(
permalinkResponseJsonParserMethod, permalinkResponseJsonParserMethodMatch,
storyUrlResponseJsonParserMethod, storyUrlResponseJsonParserMethodMatch,
profileUrlResponseJsonParserMethod, profileUrlResponseJsonParserMethodMatch,
liveUrlResponseJsonParserMethod, liveUrlResponseJsonParserMethodMatch,
) )
for (method in methodsToPatch) { for (match in methodsToPatch) {
method.apply { match.method.apply {
val putSharingUrlIndex = indexOfFirstInstruction( val putSharingUrlIndex = indexOfFirstInstruction(
indexOfFirstStringInstruction("permalink"), match.indices.first(),
Opcode.IPUT_OBJECT, Opcode.IPUT_OBJECT,
) )

View file

@ -0,0 +1,34 @@
package app.revanced.patches.instagram.misc.share
import app.revanced.patcher.firstMethodComposite
import app.revanced.patcher.instructions
import app.revanced.patcher.invoke
import app.revanced.patcher.name
internal val permalinkResponseJsonParserMethodMatch = firstMethodComposite(
"PermalinkResponse",
) {
name("parseFromJson")
instructions("permalink"())
}
internal val storyUrlResponseJsonParserMethodMatch = firstMethodComposite(
"StoryItemUrlResponse",
) {
name("parseFromJson")
instructions("story_item_to_share_url"())
}
internal val profileUrlResponseJsonParserMethodMatch = firstMethodComposite(
"ProfileUrlResponse",
) {
name("parseFromJson")
instructions("profile_to_share_url"())
}
internal val liveUrlResponseJsonParserMethodMatch = firstMethodComposite(
"LiveItemLinkUrlResponse",
) {
name("parseFromJson")
instructions("live_to_share_url"())
}

View file

@ -1,28 +0,0 @@
package app.revanced.patches.instagram.misc.share
import app.revanced.patcher.*
import app.revanced.patcher.patch.BytecodePatchContext
internal val BytecodePatchContext.permalinkResponseJsonParserMethod by gettingFirstMutableMethodDeclaratively(
"permalink", "PermalinkResponse",
) {
name("parseFromJson")
}
internal val BytecodePatchContext.storyUrlResponseJsonParserMethod by gettingFirstMutableMethodDeclaratively(
"story_item_to_share_url", "StoryItemUrlResponse",
) {
name("parseFromJson")
}
internal val BytecodePatchContext.profileUrlResponseJsonParserMethod by gettingFirstMutableMethodDeclaratively(
"profile_to_share_url", "ProfileUrlResponse",
) {
name("parseFromJson")
}
internal val BytecodePatchContext.liveUrlResponseJsonParserMethod by gettingFirstMutableMethodDeclaratively(
"live_to_share_url", "LiveItemLinkUrlResponse",
) {
name("parseFromJson")
}

View file

@ -5,9 +5,9 @@ import app.revanced.patcher.patch.BytecodePatchContext
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal val BytecodePatchContext.getCustomShareDomainMethod by gettingFirstMutableMethodDeclaratively { internal val BytecodePatchContext.getCustomShareDomainMethod by gettingFirstMutableMethodDeclaratively {
name("getCustomShareDomain")
definingClass(EXTENSION_CLASS_DESCRIPTOR)
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
returnType("Ljava/lang/String;") returnType("Ljava/lang/String;")
parameterTypes() parameterTypes()
name("getCustomShareDomain")
definingClass(EXTENSION_CLASS_DESCRIPTOR)
} }

View file

@ -2,20 +2,16 @@ package app.revanced.patches.instagram.misc.signature
import app.revanced.patcher.* import app.revanced.patcher.*
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.util.getReference import com.android.tools.smali.dexlib2.iface.ClassDef
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val isValidSignatureClassMethodMatch = firstMethodComposite( context(_: BytecodePatchContext)
"The provider for uri '", "' is not trusted: ", internal fun ClassDef.getIsValidSignatureClassMethod() = firstMutableMethodDeclaratively(
"The provider for uri '",
"' is not trusted: ",
) )
internal val BytecodePatchContext.isValidSignatureMethodMethod by gettingFirstMutableMethodDeclaratively { internal val BytecodePatchContext.isValidSignatureMethodMethod by gettingFirstMutableMethodDeclaratively {
parameterTypes("L", "Z") parameterTypes("L", "Z")
returnType("Z") returnType("Z")
custom { instructions(method("keySet"))
indexOfFirstInstruction {
getReference<MethodReference>()?.name == "keySet"
} >= 0
}
} }

View file

@ -1,5 +1,6 @@
package app.revanced.patches.instagram.misc.signature package app.revanced.patches.instagram.misc.signature
import app.revanced.patcher.immutableClassDef
import app.revanced.patcher.patch.creatingBytecodePatch import app.revanced.patcher.patch.creatingBytecodePatch
import app.revanced.util.returnEarly import app.revanced.util.returnEarly
@ -12,9 +13,6 @@ val `Disable signature check` by creatingBytecodePatch(
compatibleWith("com.instagram.android") compatibleWith("com.instagram.android")
apply { apply {
isValidSignatureMethodMethod isValidSignatureMethodMethod.immutableClassDef.getIsValidSignatureClassMethod().returnEarly(true)
.match(isValidSignatureClassMethodMatch.classDef)
.method
.returnEarly(true)
} }
} }

View file

@ -13,7 +13,8 @@ internal val metaAIKillSwitchCheckMethodMatch = firstMethodComposite("SearchAiag
opcodes(Opcode.CONST_WIDE) opcodes(Opcode.CONST_WIDE)
} }
internal val extensionMethodMethodMatch = firstMethodComposite("REPLACED_BY_PATCH") { internal val extensionMethodMatch = firstMethodComposite {
name(EXTENSION_METHOD_NAME) name(EXTENSION_METHOD_NAME)
definingClass(EXTENSION_CLASS_DESCRIPTOR) definingClass(EXTENSION_CLASS_DESCRIPTOR)
instructions("REPLACED_BY_PATCH"())
} }

View file

@ -39,12 +39,10 @@ val `Remove Meta AI` by creatingBytecodePatch(
}.toString().substring(0, 7) }.toString().substring(0, 7)
// Replace placeholder in the extension method. // Replace placeholder in the extension method.
extensionMethodMethodMatch.let { extensionMethodMatch.let {
it.method.replaceInstruction( it.method.replaceInstruction(
it.indices.first(), it.indices.first(),
""" "const-string v1, \"$relevantDigits\"",
const-string v1, "$relevantDigits"
""",
) )
} }
} }

View file

@ -55,9 +55,9 @@ val `Change start page` by creatingBytecodePatch(
) )
// Hook browseId. // Hook browseId.
browseIdMethod.let { browseIdMethodMatch.let {
it.method.apply { it.method.apply {
val browseIdIndex = it.instructionMatches.first().index val browseIdIndex = it.indices.first()
val browseIdRegister = getInstruction<OneRegisterInstruction>(browseIdIndex).registerA val browseIdRegister = getInstruction<OneRegisterInstruction>(browseIdIndex).registerA
addInstructions( addInstructions(

View file

@ -10,12 +10,11 @@ internal val BytecodePatchContext.intentActionMethod by gettingFirstMutableMetho
parameterTypes("Landroid/content/Intent;") parameterTypes("Landroid/content/Intent;")
} }
internal val BytecodePatchContext.browseIdMethod by gettingFirstMutableMethodDeclaratively( internal val browseIdMethodMatch = firstMethodComposite {
"FEwhat_to_watch",
) {
returnType("Lcom/google/android/apps/youtube/app/common/ui/navigation/PaneDescriptor;") returnType("Lcom/google/android/apps/youtube/app/common/ui/navigation/PaneDescriptor;")
// parameterTypes() // 20.30 and earlier is no parameters. 20.31+ parameter is L. // parameterTypes() // 20.30 and earlier is no parameters. 20.31+ parameter is L.
instructions( instructions(
"FEwhat_to_watch"(),
512L(), 512L(),
allOf(Opcode.IPUT_OBJECT(), field { type == "Ljava/lang/String;" }), allOf(Opcode.IPUT_OBJECT(), field { type == "Ljava/lang/String;" }),
) )

View file

@ -1,24 +1,21 @@
package app.revanced.patches.youtube.layout.theme package app.revanced.patches.youtube.layout.theme
import app.revanced.patcher.* import app.revanced.patcher.*
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
internal val BytecodePatchContext.useGradientLoadingScreenMethod by gettingFirstMutableMethodDeclaratively { internal val useGradientLoadingScreenMethodMatch = firstMethodComposite {
instructions( instructions(45412406L())
45412406L(),
)
} }
internal val BytecodePatchContext.splashScreenStyleMethod by gettingFirstMutableMethodDeclaratively { internal val splashScreenStyleMethodMatch = firstMethodComposite {
definingClass(YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE)
name("onCreate")
returnType("V") returnType("V")
parameterTypes("Landroid/os/Bundle;") parameterTypes("Landroid/os/Bundle;")
instructions( instructions(
anyInstruction( anyOf(
1074339245L(), // 20.30+ 1074339245L(), // 20.30+
269032877L(), // 20.29 and lower. 269032877L(), // 20.29 and lower.
), ),
) )
definingClass(YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE)
name("onCreate")
} }

View file

@ -200,15 +200,15 @@ val themePatch = baseThemePatch(
) )
} }
useGradientLoadingScreenMethod.insertLiteralOverride( useGradientLoadingScreenMethodMatch.method.insertLiteralOverride(
45412406L, useGradientLoadingScreenMethodMatch.indices.first(),
"$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z", "$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z",
) )
if (is_19_47_or_greater) { if (is_19_47_or_greater) {
// Lottie splash screen exists in earlier versions, but it may not be always on. // Lottie splash screen exists in earlier versions, but it may not be always on.
splashScreenStyleMethod.insertLiteralOverride( splashScreenStyleMethodMatch.method.insertLiteralOverride(
1074339245L, splashScreenStyleMethodMatch.indices.first(),
"$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I", "$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I",
) )
} }

View file

@ -1,13 +1,15 @@
package app.revanced.patches.youtube.misc.dimensions.spoof package app.revanced.patches.youtube.misc.dimensions.spoof
import app.revanced.patcher.* import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
import app.revanced.patcher.instructions
import app.revanced.patcher.invoke
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.returnType
// Strings are partial matches (format delimiters), so keep in instructions block. internal val BytecodePatchContext.deviceDimensionsModelToStringMethod by gettingFirstMutableMethodDeclaratively {
internal val deviceDimensionsModelToStringMethodMatch = firstMethodComposite {
returnType("L") returnType("L")
strings { instructions(
+"minh." "minh."(),
+";maxh." ";maxh."(),
} )
} }

View file

@ -1,6 +1,8 @@
package app.revanced.patches.youtube.misc.dimensions.spoof package app.revanced.patches.youtube.misc.dimensions.spoof
import app.revanced.patcher.classDef
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.firstMutableMethod
import app.revanced.patcher.patch.creatingBytecodePatch import app.revanced.patcher.patch.creatingBytecodePatch
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
@ -38,21 +40,20 @@ val `Spoof device dimensions` by creatingBytecodePatch(
SwitchPreference("revanced_spoof_device_dimensions"), SwitchPreference("revanced_spoof_device_dimensions"),
) )
deviceDimensionsModelToStringMethodMatch.classDef.methods.first { method -> method.name == "<init>" } // Override the parameters containing the dimensions.
// Override the parameters containing the dimensions. deviceDimensionsModelToStringMethod.classDef.methods.firstMutableMethod { name == "<init>" }.addInstructions(
.addInstructions( 1, // Add after super call.
1, // Add after super call. arrayOf(
arrayOf( 1 to "MinHeightOrWidth", // p1 = min height
1 to "MinHeightOrWidth", // p1 = min height 2 to "MaxHeightOrWidth", // p2 = max height
2 to "MaxHeightOrWidth", // p2 = max height 3 to "MinHeightOrWidth", // p3 = min width
3 to "MinHeightOrWidth", // p3 = min width 4 to "MaxHeightOrWidth", // p4 = max width
4 to "MaxHeightOrWidth", // p4 = max width ).map { (parameter, method) ->
).map { (parameter, method) -> """
""" invoke-static { p$parameter }, $EXTENSION_CLASS_DESCRIPTOR->get$method(I)I
invoke-static { p$parameter }, $EXTENSION_CLASS_DESCRIPTOR->get$method(I)I move-result p$parameter
move-result p$parameter """
""" }.joinToString("\n") { it },
}.joinToString("\n") { it }, )
)
} }
} }

View file

@ -1,7 +1,6 @@
package app.revanced.patches.youtube.misc.gms package app.revanced.patches.youtube.misc.gms
import app.revanced.patcher.* import app.revanced.patcher.*
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patches.shared.misc.mapping.ResourceType import app.revanced.patches.shared.misc.mapping.ResourceType
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@ -14,7 +13,7 @@ internal val specificNetworkErrorViewControllerMethodMatch = firstMethodComposit
ResourceType.DRAWABLE("ic_offline_no_content_upside_down"), ResourceType.DRAWABLE("ic_offline_no_content_upside_down"),
ResourceType.STRING("offline_no_content_body_text_not_offline_eligible"), ResourceType.STRING("offline_no_content_body_text_not_offline_eligible"),
method { name == "getString" && returnType == "Ljava/lang/String;" }, method { name == "getString" && returnType == "Ljava/lang/String;" },
Opcode.MOVE_RESULT_OBJECT(), after(Opcode.MOVE_RESULT_OBJECT()),
) )
} }
@ -28,6 +27,6 @@ internal val loadingFrameLayoutControllerMethodMatch = firstMethodComposite {
ResourceType.DRAWABLE("ic_offline_no_content_upside_down"), ResourceType.DRAWABLE("ic_offline_no_content_upside_down"),
ResourceType.STRING("offline_no_content_body_text_not_offline_eligible"), ResourceType.STRING("offline_no_content_body_text_not_offline_eligible"),
method { name == "getString" && returnType == "Ljava/lang/String;" }, method { name == "getString" && returnType == "Ljava/lang/String;" },
Opcode.MOVE_RESULT_OBJECT(), after(Opcode.MOVE_RESULT_OBJECT()),
) )
} }

View file

@ -1,8 +1,10 @@
package app.revanced.patches.youtube.misc.imageurlhook package app.revanced.patches.youtube.misc.imageurlhook
import app.revanced.patcher.classDef
import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instructions import app.revanced.patcher.extensions.instructions
import app.revanced.patcher.immutableClassDef
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.util.getReference import app.revanced.util.getReference
@ -30,14 +32,9 @@ val cronetImageUrlHookPatch = bytecodePatch(
dependsOn(sharedExtensionPatch) dependsOn(sharedExtensionPatch)
apply { apply {
loadImageUrlMethod = messageDigestImageUrlMethod loadImageUrlMethod = messageDigestImageUrlParentMethod.immutableClassDef.getMessageDigestImageUrlMethod()
.match(messageDigestImageUrlParentMethodMatch.classDef) loadImageSuccessCallbackMethod = onResponseStartedMethod.immutableClassDef.getOnSucceededMethod()
loadImageErrorCallbackMethod = onResponseStartedMethod.immutableClassDef.getOnFailureMethod()
loadImageSuccessCallbackMethod = onSucceededMethod
.match(onResponseStartedMethodMatch.classDef)
loadImageErrorCallbackMethod = onFailureMethod
.match(onResponseStartedMethodMatch.classDef)
// The URL is required for the failure callback hook, but the URL field is obfuscated. // The URL is required for the failure callback hook, but the URL field is obfuscated.
// Add a helper get method that returns the URL field. // Add a helper get method that returns the URL field.

View file

@ -3,8 +3,11 @@ package app.revanced.patches.youtube.misc.imageurlhook
import app.revanced.patcher.* import app.revanced.patcher.*
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.iface.ClassDef
internal val BytecodePatchContext.onFailureMethod by gettingFirstMutableMethodDeclaratively { context(_: BytecodePatchContext)
internal fun ClassDef.getOnFailureMethod() = firstMutableMethodDeclaratively {
name("onFailed")
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returnType("V") returnType("V")
parameterTypes( parameterTypes(
@ -12,49 +15,50 @@ internal val BytecodePatchContext.onFailureMethod by gettingFirstMutableMethodDe
"Lorg/chromium/net/UrlResponseInfo;", "Lorg/chromium/net/UrlResponseInfo;",
"Lorg/chromium/net/CronetException;", "Lorg/chromium/net/CronetException;",
) )
name("onFailed")
} }
// Acts as a parent fingerprint. // Acts as a parent fingerprint.
internal val onResponseStartedMethodMatch = firstMethodComposite( internal val BytecodePatchContext.onResponseStartedMethod by gettingFirstMutableMethodDeclaratively(
"Content-Length", "Content-Length",
"Content-Type", "Content-Type",
"identity", "identity",
"application/x-protobuf", "application/x-protobuf",
) { ) {
name("onResponseStarted")
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returnType("V") returnType("V")
parameterTypes("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;") parameterTypes("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;")
name("onResponseStarted")
} }
internal val BytecodePatchContext.onSucceededMethod by gettingFirstMutableMethodDeclaratively { context(_: BytecodePatchContext)
internal fun ClassDef.getOnSucceededMethod() = firstMutableMethodDeclaratively {
name("onSucceeded")
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returnType("V") returnType("V")
parameterTypes("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;") parameterTypes("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;")
name("onSucceeded")
} }
internal const val CRONET_URL_REQUEST_CLASS_DESCRIPTOR = "Lorg/chromium/net/impl/CronetUrlRequest;" internal const val CRONET_URL_REQUEST_CLASS_DESCRIPTOR = "Lorg/chromium/net/impl/CronetUrlRequest;"
internal val BytecodePatchContext.requestMethod by gettingFirstMutableMethodDeclaratively { internal val BytecodePatchContext.requestMethod by gettingFirstMutableMethodDeclaratively {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
definingClass(CRONET_URL_REQUEST_CLASS_DESCRIPTOR) definingClass(CRONET_URL_REQUEST_CLASS_DESCRIPTOR)
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
} }
internal val BytecodePatchContext.messageDigestImageUrlMethod by gettingFirstMutableMethodDeclaratively { context(_: BytecodePatchContext)
internal fun ClassDef.getMessageDigestImageUrlMethod() = firstMutableMethodDeclaratively {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameterTypes("Ljava/lang/String;", "L") parameterTypes("Ljava/lang/String;", "L")
} }
internal val messageDigestImageUrlParentMethodMatch = firstMethodComposite { internal val BytecodePatchContext.messageDigestImageUrlParentMethod by gettingFirstMutableMethodDeclaratively {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returnType("Ljava/lang/String;") returnType("Ljava/lang/String;")
parameterTypes() parameterTypes()
strings { instructions(
anyOf( anyOf(
"@#&=*+-_.,:!?()/~'%;\$", "@#&=*+-_.,:!?()/~'%;$"(),
"@#&=*+-_.,:!?()/~'%;\$[]", // 20.38+ "@#&=*+-_.,:!?()/~'%;$[]"(), // 20.38+
) ),
} )
} }

View file

@ -10,13 +10,10 @@ internal val abUriParserLegacyMethodMatch = firstMethodComposite {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returnType("Ljava/lang/Object;") returnType("Ljava/lang/Object;")
parameterTypes("Ljava/lang/Object;") parameterTypes("Ljava/lang/Object;")
strings {
// Partial string match - keep in instructions block
+"Found entityKey=`"
// "that does not contain a PlaylistVideoEntityId" - partial, skipped
}
instructions( instructions(
method { smali == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" }, "Found entityKey=`"(),
"that does not contain a PlaylistVideoEntityId"(String::contains),
method { toString() == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" },
) )
} }
@ -30,10 +27,10 @@ internal val abUriParserMethodMatch = firstMethodComposite {
instructions( instructions(
// Method is a switch statement of unrelated code, // Method is a switch statement of unrelated code,
// and there's no strings or anything unique to fingerprint. // and there's no strings or anything unique to fingerprint.
method { smali == "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;" }, method { toString() == "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;" },
method { smali == "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;" }, method { toString() == "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;" },
method { smali == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" }, method { toString() == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" },
method { smali == "Ljava/util/List;->get(I)Ljava/lang/Object;" }, method { toString() == "Ljava/util/List;->get(I)Ljava/lang/Object;" },
) )
} }
@ -42,11 +39,9 @@ internal val httpUriParserMethodMatch = firstMethodComposite {
returnType("Landroid/net/Uri;") returnType("Landroid/net/Uri;")
parameterTypes("Ljava/lang/String;") parameterTypes("Ljava/lang/String;")
instructions( instructions(
method { smali == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" }, method { toString() == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" },
"https"(),
"://"(),
"https:"(),
) )
strings {
+"https"
+"://"
+"https:"
}
} }

View file

@ -12,6 +12,7 @@ import app.revanced.patcher.returnType
import app.revanced.util.literal import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef
internal val BytecodePatchContext.videoQualityItemOnClickParentMethod by gettingFirstMethodDeclaratively( internal val BytecodePatchContext.videoQualityItemOnClickParentMethod by gettingFirstMethodDeclaratively(
"VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT", "VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT",
@ -20,7 +21,7 @@ internal val BytecodePatchContext.videoQualityItemOnClickParentMethod by getting
} }
context(_: BytecodePatchContext) context(_: BytecodePatchContext)
internal fun com.android.tools.smali.dexlib2.iface.ClassDef.getVideoQualityItemOnClickMethod() = firstMutableMethodDeclaratively { internal fun ClassDef.getVideoQualityItemOnClickMethod() = firstMutableMethodDeclaratively {
name("onItemClick") name("onItemClick")
returnType("V") returnType("V")
parameterTypes( parameterTypes(

View file

@ -140,7 +140,8 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
// Get the "showOldPlaybackSpeedMenu" method. // Get the "showOldPlaybackSpeedMenu" method.
// This is later called on the field INSTANCE. // This is later called on the field INSTANCE.
val showOldPlaybackSpeedMenuMethod = getOldPlaybackSpeedsMethod.classDef.getShowOldPlaybackSpeedMenuMethod() val showOldPlaybackSpeedMenuMethod =
getOldPlaybackSpeedsMethod.immutableClassDef.getShowOldPlaybackSpeedMenuMethod()
// Insert the call to the "showOldPlaybackSpeedMenu" method on the field INSTANCE. // Insert the call to the "showOldPlaybackSpeedMenu" method on the field INSTANCE.
showOldPlaybackSpeedMenuExtensionMethod.apply { showOldPlaybackSpeedMenuExtensionMethod.apply {

View file

@ -16,8 +16,8 @@ internal fun ClassDef.getVideoIdMethodMatch() = firstMethodComposite {
parameterTypes("L") parameterTypes("L")
instructions( instructions(
method { method {
definingClass == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" definingClass == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" &&
&& returnType == "Ljava/lang/String;" returnType == "Ljava/lang/String;"
}, },
Opcode.MOVE_RESULT_OBJECT(), Opcode.MOVE_RESULT_OBJECT(),
) )
@ -29,8 +29,8 @@ internal val videoIdBackgroundPlayMethodMatch = firstMethodComposite {
parameterTypes("L") parameterTypes("L")
instructions( instructions(
method { method {
definingClass == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" definingClass == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" &&
&& returnType == "Ljava/lang/String;" returnType == "Ljava/lang/String;"
}, },
Opcode.MOVE_RESULT_OBJECT(), Opcode.MOVE_RESULT_OBJECT(),
Opcode.IPUT_OBJECT(), Opcode.IPUT_OBJECT(),
@ -40,11 +40,8 @@ internal val videoIdBackgroundPlayMethodMatch = firstMethodComposite {
Opcode.RETURN_VOID(), Opcode.RETURN_VOID(),
) )
custom { custom {
implementation != null && immutableClassDef.methods.count() == 17 || // 20.39 and lower.
( immutableClassDef.methods.count() == 16 // 20.40+
definingClass.methods.count() == 17 || // 20.39 and lower.
definingClass.methods.count() == 16
) // 20.40+
} }
} }

View file

@ -92,17 +92,19 @@ val videoIdPatch = bytecodePatch(
) )
apply { apply {
videoIdParentMethodMatch.classDef.getVideoIdMethodMatch().let { videoIdParentMethodMatch.immutableClassDef.getVideoIdMethodMatch().let {
videoIdMethod = it.method videoIdMethod = it.method
val index = it.indices.first() val index = it.indices.first()
videoIdRegister = videoIdMethod.getInstruction<OneRegisterInstruction>(index + 1).registerA videoIdRegister = it.method.getInstruction<OneRegisterInstruction>(index + 1).registerA
videoIdInsertIndex = index + 2 videoIdInsertIndex = index + 2
} }
videoIdBackgroundPlayMethodMatch.let { videoIdBackgroundPlayMethodMatch.let {
backgroundPlaybackMethod = it.method backgroundPlaybackMethod = it.method
val index = it.indices.first() val index = it.indices.first()
backgroundPlaybackVideoIdRegister = backgroundPlaybackMethod.getInstruction<OneRegisterInstruction>(index + 1).registerA backgroundPlaybackVideoIdRegister = it.method.getInstruction<OneRegisterInstruction>(index + 1).registerA
backgroundPlaybackInsertIndex = index + 2 backgroundPlaybackInsertIndex = index + 2
} }
} }