From 8427f28208f1cf4c8428a0081d1c0811991b52b3 Mon Sep 17 00:00:00 2001 From: inotia00 Date: Sat, 18 Feb 2023 14:18:23 +0900 Subject: [PATCH] add suport YouTube v18.06.35 --- .../shared/annotation/YouTubeCompatibility.kt | 2 +- .../MainstreamVideoAdsFingerprint.kt | 3 - .../PivotBarCreateButtonViewFingerprint.kt | 1 - .../patch/videoads/GeneralVideoAdsPatch.kt | 36 ++++---- .../patch/HideFullscreenPanelsPatch.kt | 41 +++++---- .../CrowdfundingBoxFingerprint.kt | 20 ++++ .../patch/CrowdfundingBoxPatch.kt | 92 +++++++------------ ...niPlayerDimensionsCalculatorFingerprint.kt | 4 +- .../MiniPlayerOverrideFingerprint.kt | 2 +- .../MiniPlayerOverrideParentFingerprint.kt | 12 +++ .../patch/TabletMiniPlayerPatch.kt | 51 ++++++---- .../patch/HideAutoplayButtonPatch.kt | 13 ++- .../resourceid/patch/SharedResourceIdPatch.kt | 2 + .../fingerprints/DislikeFingerprint.kt | 3 - .../fingerprints/LikeFingerprint.kt | 3 - .../fingerprints/RemoveLikeFingerprint.kt | 3 - .../ShortsTextComponentParentFingerprint.kt | 7 ++ .../TextComponentSpecFingerprint.kt | 18 ++-- .../TextComponentSpecParentFingerprint.kt | 11 +++ .../patch/ReturnYouTubeDislikePatch.kt | 88 +++++++++++++----- .../VideoQualitySetterFingerprint.kt | 11 +-- .../VideoQualitySettingsFingerprint.kt | 17 ++++ .../VideoQualitySettingsParentFingerprint.kt | 12 +++ .../VideoUserQualityChangeFingerprint.kt | 9 +- .../patch/VideoQualityBytecodePatch.kt | 48 ++++++---- 25 files changed, 315 insertions(+), 194 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/general/crowdfundingbox/fingerprints/CrowdfundingBoxFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerOverrideParentFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySettingsFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySettingsParentFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/shared/annotation/YouTubeCompatibility.kt b/src/main/kotlin/app/revanced/patches/shared/annotation/YouTubeCompatibility.kt index 2e0be79bf..9b06a8783 100644 --- a/src/main/kotlin/app/revanced/patches/shared/annotation/YouTubeCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/shared/annotation/YouTubeCompatibility.kt @@ -3,7 +3,7 @@ package app.revanced.patches.shared.annotation import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Package -@Compatibility([Package("com.google.android.youtube", arrayOf("18.05.40"))]) +@Compatibility([Package("com.google.android.youtube", arrayOf("18.06.35"))]) @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.RUNTIME) internal annotation class YouTubeCompatibility diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/MainstreamVideoAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/MainstreamVideoAdsFingerprint.kt index 4fde3e1f0..e8501858e 100644 --- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/MainstreamVideoAdsFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/MainstreamVideoAdsFingerprint.kt @@ -1,13 +1,10 @@ package app.revanced.patches.shared.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode object MainstreamVideoAdsFingerprint : MethodFingerprint( returnType = "V", - access = AccessFlags.PRIVATE or AccessFlags.FINAL, parameters = listOf("L","Z"), opcodes = listOf( Opcode.IGET_OBJECT, diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/PivotBarCreateButtonViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/PivotBarCreateButtonViewFingerprint.kt index 408407c78..d914107e0 100644 --- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/PivotBarCreateButtonViewFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/PivotBarCreateButtonViewFingerprint.kt @@ -10,7 +10,6 @@ import org.jf.dexlib2.Opcode object PivotBarCreateButtonViewFingerprint : MethodFingerprint( returnType = "V", access = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = listOf("Z"), customFingerprint = { methodDef -> methodDef.implementation?.instructions?.any { it.opcode.ordinal == Opcode.CONST.ordinal && diff --git a/src/main/kotlin/app/revanced/patches/shared/patch/videoads/GeneralVideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/patch/videoads/GeneralVideoAdsPatch.kt index 9d3188a51..d19f3fb6a 100644 --- a/src/main/kotlin/app/revanced/patches/shared/patch/videoads/GeneralVideoAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/patch/videoads/GeneralVideoAdsPatch.kt @@ -8,6 +8,7 @@ import app.revanced.patcher.data.toMethodWalker import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.instruction import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess @@ -26,34 +27,30 @@ class GeneralVideoAdsPatch : BytecodePatch( ) ) { override fun execute(context: BytecodeContext): PatchResult { - val LegacyVideoAdsResult = LegacyVideoAdsFingerprint.result ?: return LegacyVideoAdsFingerprint.toErrorResult() + val legacyVideoAdsResult = LegacyVideoAdsFingerprint.result ?: return LegacyVideoAdsFingerprint.toErrorResult() - LegacyVideoAdsMethod = - context.toMethodWalker(LegacyVideoAdsResult.method) + legacyVideoAdsMethod = + context.toMethodWalker(legacyVideoAdsResult.method) .nextMethod(13, true) .getMethod() as MutableMethod - MainstreamVideoAdsFingerprint.resolve(context, MainstreamVideoAdsParentFingerprint.result!!.classDef) - - val MainstreamAdsResult = MainstreamVideoAdsFingerprint.result ?: return MainstreamVideoAdsFingerprint.toErrorResult() - - MainstreamVideoAdsMethod = MainstreamAdsResult.mutableMethod - - InsertIndex = MainstreamAdsResult.scanResult.patternScanResult!!.endIndex + MainstreamVideoAdsParentFingerprint.result?.let { parentResult -> + MainstreamVideoAdsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { + mainstreamVideoAdsResult = it + } ?: return MainstreamVideoAdsFingerprint.toErrorResult() + } ?: return MainstreamVideoAdsParentFingerprint.toErrorResult() return PatchResultSuccess() } internal companion object { - var InsertIndex: Int = 0 - - lateinit var LegacyVideoAdsMethod: MutableMethod - lateinit var MainstreamVideoAdsMethod: MutableMethod + lateinit var legacyVideoAdsMethod: MutableMethod + lateinit var mainstreamVideoAdsResult: MethodFingerprintResult fun injectLegacyAds( descriptor: String ) { - LegacyVideoAdsMethod.addInstructions( + legacyVideoAdsMethod.addInstructions( 0, """ invoke-static {}, $descriptor move-result v1 @@ -64,13 +61,16 @@ class GeneralVideoAdsPatch : BytecodePatch( fun injectMainstreamAds( descriptor: String ) { - MainstreamVideoAdsMethod.addInstructions( - InsertIndex, """ + val mainstreamVideoAdsMethod = mainstreamVideoAdsResult.mutableMethod + val insertIndex = mainstreamVideoAdsResult.scanResult.patternScanResult!!.endIndex + + mainstreamVideoAdsMethod.addInstructions( + insertIndex, """ invoke-static {}, $descriptor move-result v1 if-nez v1, :show_video_ads return-void - """, listOf(ExternalLabel("show_video_ads", MainstreamVideoAdsMethod.instruction(InsertIndex))) + """, listOf(ExternalLabel("show_video_ads", mainstreamVideoAdsMethod.instruction(insertIndex))) ) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreen/fullscreenpanels/patch/HideFullscreenPanelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreen/fullscreenpanels/patch/HideFullscreenPanelsPatch.kt index 596cce92c..589a7633f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreen/fullscreenpanels/patch/HideFullscreenPanelsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreen/fullscreenpanels/patch/HideFullscreenPanelsPatch.kt @@ -20,7 +20,9 @@ import app.revanced.patches.youtube.layout.fullscreen.fullscreenpanels.fingerpri import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.util.integrations.Constants.FULLSCREEN_LAYOUT import org.jf.dexlib2.Opcode +import org.jf.dexlib2.builder.instruction.BuilderInstruction21c import org.jf.dexlib2.builder.instruction.BuilderInstruction35c +import org.jf.dexlib2.iface.instruction.formats.Instruction21c import org.jf.dexlib2.iface.instruction.formats.Instruction35c @Patch @@ -57,6 +59,29 @@ class HideFullscreenPanelsPatch : BytecodePatch( } } ?: return FullscreenViewAdderFingerprint.toErrorResult() + LayoutConstructorFingerprint.result?.mutableMethod?.let { method -> + val instructions = method.implementation!!.instructions + val registerIndex = instructions.indexOfFirst { + it.opcode == Opcode.CONST_STRING && + (it as BuilderInstruction21c).reference.toString() == "1.0x" + } + val dummyRegister = (instructions[registerIndex] as Instruction21c).registerA + + val invokeIndex = method.implementation!!.instructions.indexOfFirst { + it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal && + ((it as? BuilderInstruction35c)?.reference.toString() == + "Landroid/widget/FrameLayout;->addView(Landroid/view/View;)V") + } + + method.addInstructions( + invokeIndex, """ + invoke-static {}, $FULLSCREEN_LAYOUT->hideFullscreenPanel()Z + move-result v$dummyRegister + if-nez v$dummyRegister, :hidden + """, listOf(ExternalLabel("hidden", method.instruction(invokeIndex + 1))) + ) + } ?: return LayoutConstructorFingerprint.toErrorResult() + /* * Add settings */ @@ -70,22 +95,6 @@ class HideFullscreenPanelsPatch : BytecodePatch( SettingsPatch.updatePatchStatus("hide-fullscreen-panels") - LayoutConstructorFingerprint.result?.mutableMethod?.let { method -> - val invokeIndex = method.implementation!!.instructions.indexOfFirst { - it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal && - ((it as? BuilderInstruction35c)?.reference.toString() == - "Landroid/widget/FrameLayout;->addView(Landroid/view/View;)V") - } - - method.addInstructions( - invokeIndex, """ - invoke-static {}, $FULLSCREEN_LAYOUT->hideFullscreenPanel()Z - move-result v15 - if-nez v15, :hidden - """, listOf(ExternalLabel("hidden", method.instruction(invokeIndex + 1))) - ) - } ?: return LayoutConstructorFingerprint.toErrorResult() - return PatchResultSuccess() } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/crowdfundingbox/fingerprints/CrowdfundingBoxFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/crowdfundingbox/fingerprints/CrowdfundingBoxFingerprint.kt new file mode 100644 index 000000000..188fc1c3a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/crowdfundingbox/fingerprints/CrowdfundingBoxFingerprint.kt @@ -0,0 +1,20 @@ +package app.revanced.patches.youtube.layout.general.crowdfundingbox.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction + +object CrowdfundingBoxFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IPUT_OBJECT + ), + customFingerprint = { methodDef -> + methodDef.implementation?.instructions?.any { + it.opcode.ordinal == Opcode.CONST.ordinal && + (it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.donationCompanionResourceId + } == true + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/crowdfundingbox/patch/CrowdfundingBoxPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/crowdfundingbox/patch/CrowdfundingBoxPatch.kt index 55b66e225..3390df697 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/general/crowdfundingbox/patch/CrowdfundingBoxPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/crowdfundingbox/patch/CrowdfundingBoxPatch.kt @@ -1,90 +1,66 @@ package app.revanced.patches.youtube.layout.general.crowdfundingbox.patch -import app.revanced.extensions.findMutableMethodOf -import app.revanced.extensions.injectHideCall +import app.revanced.extensions.toErrorResult 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.extensions.instruction 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.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.shared.annotation.YouTubeCompatibility -import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch +import app.revanced.patches.youtube.layout.general.crowdfundingbox.fingerprints.CrowdfundingBoxFingerprint +import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.formats.Instruction22c -import org.jf.dexlib2.iface.instruction.formats.Instruction31i +import app.revanced.util.integrations.Constants.GENERAL_LAYOUT +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction @Patch @Name("hide-crowdfunding-box") @Description("Hides the crowdfunding box between the player and video description.") @DependsOn( [ - ResourceMappingPatch::class, - SettingsPatch::class + SettingsPatch::class, + SharedResourcdIdPatch::class ] ) @YouTubeCompatibility @Version("0.0.1") -class CrowdfundingBoxPatch : BytecodePatch() { - - // list of resource names to get the id of - private val resourceIds = arrayOf( - "donation_companion" - ).map { name -> - ResourceMappingPatch.resourceMappings.single { it.name == name }.id - } - private var patchSuccessArray = Array(resourceIds.size) {false} - +class CrowdfundingBoxPatch : BytecodePatch( + listOf( + CrowdfundingBoxFingerprint + ) +) { override fun execute(context: BytecodeContext): PatchResult { - context.classes.forEach { classDef -> - classDef.methods.forEach { method -> - with(method.implementation) { - this?.instructions?.forEachIndexed { index, instruction -> - when (instruction.opcode) { - Opcode.CONST -> { - when ((instruction as Instruction31i).wideLiteral) { - resourceIds[0] -> { // crowdfunding - val insertIndex = index + 3 - val iPutInstruction = instructions.elementAt(insertIndex) - if (iPutInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) + CrowdfundingBoxFingerprint.result?.let { + with (it.mutableMethod) { + val insertIndex = it.scanResult.patternScanResult!!.endIndex + val register = (instruction(insertIndex) as TwoRegisterInstruction).registerA - val viewRegister = (iPutInstruction as Instruction22c).registerA - mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "layout/GeneralLayoutPatch", "hideCrowdfundingBox") - patchSuccessArray[0] = true; - } - } - } - else -> return@forEachIndexed - } - } - } - } - } - - val errorIndex: Int = patchSuccessArray.indexOf(false) - - if (errorIndex == -1) { - /* - * Add settings - */ - SettingsPatch.addPreference( - arrayOf( - "PREFERENCE: GENERAL_LAYOUT_SETTINGS", - "SETTINGS: HIDE_CROWDFUNDING_BOX" + addInstruction( + insertIndex, + "invoke-static {v$register}, $GENERAL_LAYOUT->hideCrowdfundingBox(Landroid/view/View;)V" ) + } + } ?: return CrowdfundingBoxFingerprint.toErrorResult() + + /* + * Add settings + */ + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE: GENERAL_LAYOUT_SETTINGS", + "SETTINGS: HIDE_CROWDFUNDING_BOX" ) + ) - SettingsPatch.updatePatchStatus("hide-crowdfunding-box") + SettingsPatch.updatePatchStatus("hide-crowdfunding-box") - return PatchResultSuccess() - } else - return PatchResultError("Instruction not found: $errorIndex") + return PatchResultSuccess() } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt index 283d3ed26..ac002f5b6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt @@ -8,8 +8,8 @@ import org.jf.dexlib2.Opcode import org.jf.dexlib2.iface.instruction.WideLiteralInstruction object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "V", + access = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef -> methodDef.implementation?.instructions?.any { it.opcode.ordinal == Opcode.CONST.ordinal && diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerOverrideFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerOverrideFingerprint.kt index a957fd711..f1da3b9c3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerOverrideFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerOverrideFingerprint.kt @@ -9,5 +9,5 @@ object MiniPlayerOverrideFingerprint : MethodFingerprint( returnType = "Z", access = AccessFlags.PUBLIC or AccessFlags.STATIC, parameters = listOf("L"), - opcodes = listOf(Opcode.RETURN), // anchor to insert the instruction + opcodes = listOf(Opcode.INVOKE_STATIC), // anchor to insert the instruction ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerOverrideParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerOverrideParentFingerprint.kt new file mode 100644 index 000000000..d80571047 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/fingerprints/MiniPlayerOverrideParentFingerprint.kt @@ -0,0 +1,12 @@ +package app.revanced.patches.youtube.layout.general.tabletminiplayer.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags + +object MiniPlayerOverrideParentFingerprint : MethodFingerprint( + returnType = "L", + access = AccessFlags.PUBLIC or AccessFlags.STATIC, + parameters = listOf("L"), + strings = listOf("VIDEO_QUALITIES_QUICK_MENU_BOTTOM_SHEET_FRAGMENT") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/patch/TabletMiniPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/patch/TabletMiniPlayerPatch.kt index 1f54bf8c8..efabfcdbd 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/patch/TabletMiniPlayerPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/tabletminiplayer/patch/TabletMiniPlayerPatch.kt @@ -5,6 +5,7 @@ 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.data.toMethodWalker import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult @@ -19,6 +20,7 @@ import app.revanced.patches.youtube.layout.general.tabletminiplayer.fingerprints import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.util.integrations.Constants.GENERAL_LAYOUT +import org.jf.dexlib2.Opcode import org.jf.dexlib2.iface.instruction.OneRegisterInstruction @Patch @@ -35,31 +37,33 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction class TabletMiniPlayerPatch : BytecodePatch( listOf( MiniPlayerDimensionsCalculatorFingerprint, - MiniPlayerResponseModelSizeCheckFingerprint + MiniPlayerResponseModelSizeCheckFingerprint, + MiniPlayerOverrideParentFingerprint ) ) { override fun execute(context: BytecodeContext): PatchResult { MiniPlayerDimensionsCalculatorFingerprint.result?.let { parentResult -> - // first resolve the fingerprints via the parent fingerprint - val miniPlayerClass = parentResult.classDef - - arrayOf( - MiniPlayerOverrideNoContextFingerprint, - MiniPlayerOverrideFingerprint, - MiniPlayerResponseModelSizeCheckFingerprint - ).map { - it to (it.also { it.resolve(context, miniPlayerClass) }.result ?: return it.toErrorResult()) - }.forEach { (fingerprint, result) -> - if (fingerprint == MiniPlayerOverrideNoContextFingerprint) { - val (method, _, parameterRegister) = result.addProxyCall() - method.insertOverride(method.implementation!!.instructions.size - 1, parameterRegister) - } else { - val (_, _, _) = result.addProxyCall() - } - } + MiniPlayerOverrideNoContextFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result -> + val (method, _, parameterRegister) = result.addProxyCall() + method.insertOverride(method.implementation!!.instructions.size - 1, parameterRegister) + } ?: return MiniPlayerOverrideNoContextFingerprint.toErrorResult() } ?: return MiniPlayerDimensionsCalculatorFingerprint.toErrorResult() + MiniPlayerOverrideParentFingerprint.result?.let { parentResult -> + MiniPlayerOverrideFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result -> + (context.toMethodWalker(result.method) + .nextMethod(result.scanResult.patternScanResult!!.startIndex, true) + .getMethod() as MutableMethod) + .instructionProxyCall() + } ?: return MiniPlayerOverrideFingerprint.toErrorResult() + + } ?: return MiniPlayerOverrideParentFingerprint.toErrorResult() + + MiniPlayerResponseModelSizeCheckFingerprint.result?.let { + val (_, _, _) = it.addProxyCall() + } ?: return MiniPlayerResponseModelSizeCheckFingerprint.toErrorResult() + /* * Add settings */ @@ -94,6 +98,17 @@ class TabletMiniPlayerPatch : BytecodePatch( ) } + fun MutableMethod.instructionProxyCall() { + val insertInstructions = this.implementation!!.instructions + for ((index, instruction) in insertInstructions.withIndex()) { + if (instruction.opcode != Opcode.RETURN) continue + val parameterRegister = (instruction as OneRegisterInstruction).registerA + this.insertOverride(index, parameterRegister) + this.insertOverride(insertInstructions.size - 1, parameterRegister) + break; + } + } + fun MethodFingerprintResult.unwrap(): Triple { val scanIndex = this.scanResult.patternScanResult!!.endIndex val method = this.mutableMethod diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/autoplaybutton/patch/HideAutoplayButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/autoplaybutton/patch/HideAutoplayButtonPatch.kt index 569e70f45..427e9d4f3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/player/autoplaybutton/patch/HideAutoplayButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/autoplaybutton/patch/HideAutoplayButtonPatch.kt @@ -17,9 +17,12 @@ import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.util.integrations.Constants.PLAYER_LAYOUT +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.builder.instruction.BuilderInstruction21c import org.jf.dexlib2.iface.instruction.Instruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import org.jf.dexlib2.iface.instruction.formats.Instruction21c import org.jf.dexlib2.iface.reference.MethodReference @Patch @@ -46,6 +49,12 @@ class HideAutoplayButtonPatch : BytecodePatch( LayoutConstructorFingerprint.result?.mutableMethod?.let { method -> with (method.implementation!!.instructions) { + val registerIndex = indexOfFirst { + it.opcode == Opcode.CONST_STRING && + (it as BuilderInstruction21c).reference.toString() == "1.0x" + } + val dummyRegister = (this[registerIndex] as Instruction21c).registerA + // where to insert the branch instructions and ... val insertIndex = this.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autoNavPreviewStubId @@ -60,8 +69,8 @@ class HideAutoplayButtonPatch : BytecodePatch( method.addInstructions( insertIndex, """ invoke-static {}, $PLAYER_LAYOUT->hideAutoPlayButton()Z - move-result v15 - if-nez v15, :hidden + move-result v$dummyRegister + if-nez v$dummyRegister, :hidden """, listOf(ExternalLabel("hidden", jumpInstruction)) ) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt index 7f51467a2..5976a4253 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt @@ -24,6 +24,7 @@ class SharedResourcdIdPatch : ResourcePatch { var bottompaneloverlaytextLabelId: Long = -1 var bottomUiContainerResourceId: Long = -1 var controlsLayoutStubResourceId: Long = -1 + var donationCompanionResourceId: Long = -1 var educationTextViewResourceId: Long = -1 var emptycolorLabelId: Long = -1 var floatybarQueueLabelId: Long = -1 @@ -53,6 +54,7 @@ class SharedResourcdIdPatch : ResourcePatch { bottompaneloverlaytextLabelId = findSharedResourceId("id", "bottom_panel_overlay_text") bottomUiContainerResourceId = findSharedResourceId("id", "bottom_ui_container_stub") controlsLayoutStubResourceId = findSharedResourceId("id", "controls_layout_stub") + donationCompanionResourceId = findSharedResourceId("layout", "donation_companion") educationTextViewResourceId = findSharedResourceId("id", "user_education_text_view") emptycolorLabelId = findSharedResourceId("color", "inline_time_bar_colorized_bar_empty_color_dark") floatybarQueueLabelId = findSharedResourceId("string", "floaty_bar_queue_status") diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/DislikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/DislikeFingerprint.kt index 1d4e882ed..bc1968791 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/DislikeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/DislikeFingerprint.kt @@ -1,11 +1,8 @@ package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags object DislikeFingerprint : MethodFingerprint( returnType = "V", - access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, strings = listOf("like/dislike") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/LikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/LikeFingerprint.kt index 92f6d7e02..f524aebef 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/LikeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/LikeFingerprint.kt @@ -1,11 +1,8 @@ package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags object LikeFingerprint : MethodFingerprint( returnType = "V", - access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, strings = listOf("like/like") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt index 8e7d9a651..74c59fa2f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt @@ -1,11 +1,8 @@ package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags object RemoveLikeFingerprint : MethodFingerprint( returnType = "V", - access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, strings = listOf("like/removelike") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/ShortsTextComponentParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/ShortsTextComponentParentFingerprint.kt index 66ce47a3c..306fc66ac 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/ShortsTextComponentParentFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/ShortsTextComponentParentFingerprint.kt @@ -10,6 +10,13 @@ object ShortsTextComponentParentFingerprint : MethodFingerprint( access = AccessFlags.PROTECTED or AccessFlags.FINAL, parameters = listOf("L", "L"), opcodes = listOf( + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.GOTO, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.RETURN_VOID, Opcode.IGET_OBJECT, Opcode.CHECK_CAST, Opcode.IGET_BOOLEAN, diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/TextComponentSpecFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/TextComponentSpecFingerprint.kt index e2a2baa40..b9c39099e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/TextComponentSpecFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/TextComponentSpecFingerprint.kt @@ -1,17 +1,17 @@ package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints +import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode object TextComponentSpecFingerprint : MethodFingerprint( - returnType = "L", - access = AccessFlags.STATIC.getValue(), - opcodes = listOf(Opcode.CMPL_FLOAT), - customFingerprint = { methodDef -> - methodDef.implementation!!.instructions.any { - ((it as? NarrowLiteralInstruction)?.narrowLiteral == 16842907) - } - } + returnType = "V", + access = AccessFlags.PROTECTED or AccessFlags.FINAL, + parameters = listOf("L"), + opcodes = listOf( + Opcode.INVOKE_STATIC_RANGE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_DIRECT + ) ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt new file mode 100644 index 000000000..92bba36b4 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags + +object TextComponentSpecParentFingerprint : MethodFingerprint( + returnType = "V", + access = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR, + strings = listOf("TextComponent") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt index a54b9a6c7..9b6659730 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt @@ -7,10 +7,11 @@ import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.toMethodWalker import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.instruction import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve 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.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch @@ -20,7 +21,13 @@ import app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints.* import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.videoid.mainstream.patch.MainstreamVideoIdPatch import app.revanced.util.integrations.Constants.UTILS_PATH +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.builder.instruction.BuilderInstruction3rc import org.jf.dexlib2.iface.instruction.OneRegisterInstruction +import org.jf.dexlib2.iface.instruction.ReferenceInstruction +import org.jf.dexlib2.iface.instruction.formats.Instruction35c +import org.jf.dexlib2.iface.reference.FieldReference +import org.jf.dexlib2.iface.reference.MethodReference @Patch @Name("return-youtube-dislike") @@ -39,7 +46,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch( LikeFingerprint, RemoveLikeFingerprint, ShortsTextComponentParentFingerprint, - TextComponentSpecFingerprint + TextComponentSpecParentFingerprint ) ) { override fun execute(context: BytecodeContext): PatchResult { @@ -60,7 +67,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch( } ShortsTextComponentParentFingerprint.result?.let { - with(context + with (context .toMethodWalker(it.method) .nextMethod(it.scanResult.patternScanResult!!.endIndex, true) .getMethod() as MutableMethod @@ -69,30 +76,57 @@ class ReturnYouTubeDislikePatch : BytecodePatch( val insertIndex = insertInstructions.size - 1 val insertRegister = (insertInstructions.elementAt(insertIndex) as OneRegisterInstruction).registerA - addInstructions( - insertIndex, """ - invoke-static {v$insertRegister}, ${INTEGRATIONS_RYD_CLASS_DESCRIPTOR}->onShortsComponentCreated(Landroid/text/Spanned;)Landroid/text/Spanned; - move-result-object v$insertRegister - """ - ) + this.insertShorts(insertIndex, insertRegister) } + with (it.mutableMethod) { + val insertInstructions = this.implementation!!.instructions + val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2 + val insertRegister = (insertInstructions.elementAt(insertIndex - 1) as OneRegisterInstruction).registerA + + this.insertShorts(insertIndex, insertRegister) + } } ?: return ShortsTextComponentParentFingerprint.toErrorResult() - val createComponentResult = TextComponentSpecFingerprint.result ?: return PatchResultError("Failed to find TextComponentSpecFingerprint method.") - val createComponentMethod = createComponentResult.mutableMethod + TextComponentSpecParentFingerprint.result?.let { parentResult -> + TextComponentSpecFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { + with (it.mutableMethod) { + val startIndex = it.scanResult.patternScanResult!!.startIndex + val endIndex = it.scanResult.patternScanResult!!.endIndex - val conversionContextParam = 5 - val textRefParam = createComponentMethod.parameters.size - 2 + val dummyRegister = (instruction(startIndex) as BuilderInstruction3rc).registerCount + + (instruction(startIndex) as BuilderInstruction3rc).startRegister - 1 + val targetRegister = (instruction(endIndex) as Instruction35c).registerC - createComponentMethod.addInstructions( - 0, - """ - move-object/from16 v7, p$conversionContextParam - move-object/from16 v8, p$textRefParam - invoke-static {v7, v8}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V - """ - ) + val instructions = implementation!!.instructions + val targetString = + ((instructions.elementAt(startIndex) as ReferenceInstruction).reference as MethodReference).parameterTypes.first().toString() + + for ((index, instruction) in instructions.withIndex()) { + if (instruction.opcode != Opcode.IGET_OBJECT) continue + + val indexReference = (instruction as ReferenceInstruction).reference as FieldReference + + if (indexReference.type != targetString) continue + targetReference = indexReference + targetIndex = index + break + } + + if (targetIndex == 0) return TextComponentSpecFingerprint.toErrorResult() + + val conversionContextParam = 0 + + addInstructions( + endIndex + 1, """ + move-object/from16 v$dummyRegister, p$conversionContextParam + iget-object v$dummyRegister, v$dummyRegister, ${definingClass}->${targetReference.name}:${targetReference.type} + invoke-static {v$dummyRegister, v$targetRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V + """ + ) + } + } ?: return TextComponentSpecFingerprint.toErrorResult() + } ?: return TextComponentSpecParentFingerprint.toErrorResult() MainstreamVideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V") @@ -108,6 +142,9 @@ class ReturnYouTubeDislikePatch : BytecodePatch( private companion object { const val INTEGRATIONS_RYD_CLASS_DESCRIPTOR = "$UTILS_PATH/ReturnYouTubeDislikePatch;" + + var targetIndex: Int = 0 + private lateinit var targetReference: FieldReference } private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind) @@ -119,4 +156,13 @@ class ReturnYouTubeDislikePatch : BytecodePatch( DISLIKE(-1), REMOVE_LIKE(0) } + + private fun MutableMethod.insertShorts(index: Int, register: Int) { + addInstructions( + index, """ + invoke-static {v$register}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onShortsComponentCreated(Landroid/text/Spanned;)Landroid/text/Spanned; + move-result-object v$register + """ + ) + } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySetterFingerprint.kt index c87e6e5ed..d092b0517 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySetterFingerprint.kt @@ -3,17 +3,10 @@ package app.revanced.patches.youtube.video.quality.bytecode.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode object VideoQualitySetterFingerprint : MethodFingerprint( returnType = "V", access = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = listOf("[L", "I", "I", "Z", "I"), - opcodes = listOf( - Opcode.IF_EQZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_BOOLEAN, - ) + parameters = listOf("L"), + strings = listOf("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySettingsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySettingsFingerprint.kt new file mode 100644 index 000000000..1376e01a4 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySettingsFingerprint.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.youtube.video.quality.bytecode.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +object VideoQualitySettingsFingerprint : MethodFingerprint( + returnType = "V", + access = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("L"), + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IGET_OBJECT + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySettingsParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySettingsParentFingerprint.kt new file mode 100644 index 000000000..e83d1f219 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoQualitySettingsParentFingerprint.kt @@ -0,0 +1,12 @@ +package app.revanced.patches.youtube.video.quality.bytecode.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags + +object VideoQualitySettingsParentFingerprint : MethodFingerprint( + returnType = "V", + access = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("[L", "I", "Z"), + strings = listOf("menu_item_video_quality") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoUserQualityChangeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoUserQualityChangeFingerprint.kt index a1d41b955..38ae4dcf0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoUserQualityChangeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/fingerprints/VideoUserQualityChangeFingerprint.kt @@ -3,16 +3,9 @@ package app.revanced.patches.youtube.video.quality.bytecode.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode object VideoUserQualityChangeFingerprint : MethodFingerprint( returnType = "V", access = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = listOf("L","L","I","J"), - opcodes = listOf( - Opcode.MOVE, - Opcode.MOVE_WIDE, - Opcode.INVOKE_INTERFACE_RANGE, - Opcode.RETURN_VOID - ) + customFingerprint = { it.name == "onItemClick" } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/patch/VideoQualityBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/patch/VideoQualityBytecodePatch.kt index cf2f2f409..29f2b17fb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/patch/VideoQualityBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/bytecode/patch/VideoQualityBytecodePatch.kt @@ -13,9 +13,7 @@ import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.youtube.misc.videoid.legacy.patch.LegacyVideoIdPatch -import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoQualityReferenceFingerprint -import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoQualitySetterFingerprint -import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoUserQualityChangeFingerprint +import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.* import app.revanced.util.integrations.Constants.VIDEO_PATH import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.reference.FieldReference @@ -26,36 +24,44 @@ import org.jf.dexlib2.iface.reference.FieldReference @Version("0.0.1") class VideoQualityBytecodePatch : BytecodePatch( listOf( - VideoQualitySetterFingerprint + VideoQualitySetterFingerprint, + VideoQualitySettingsParentFingerprint ) ) { override fun execute(context: BytecodeContext): PatchResult { VideoQualitySetterFingerprint.result?.let { parentResult -> VideoQualityReferenceFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result -> val instructions = result.method.implementation!!.instructions - val qualityFieldReference = + + qualityFieldReference = (instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference - val qIndexMethodName = + qIndexMethodName = context.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name - - parentResult.mutableMethod.addInstructions( - 0, """ - iget-object v0, p0, ${result.classDef.type}->${qualityFieldReference.name}:${qualityFieldReference.type} - const-string v1, "$qIndexMethodName" - invoke-static {p1, p2, v0, v1}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I - move-result p2 - """, - ) } ?: return VideoQualityReferenceFingerprint.toErrorResult() VideoUserQualityChangeFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.addInstruction( - 0, - "invoke-static {p3}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userChangedQuality(I)V" + 0, + "invoke-static {p3}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userChangedQuality(I)V" ) ?: return VideoUserQualityChangeFingerprint.toErrorResult() - } ?: return VideoQualitySetterFingerprint.toErrorResult() + VideoQualitySettingsParentFingerprint.result?.let { parentResult -> + VideoQualitySettingsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.let { + relayFieldReference = (it.implementation!!.instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference + } ?: return VideoQualitySettingsFingerprint.toErrorResult() + + parentResult.mutableMethod.addInstructions( + 0, """ + iget-object v0, p0, ${parentResult.classDef.type}->${relayFieldReference.name}:${relayFieldReference.type} + iget-object v1, v0, ${relayFieldReference.type}->${qualityFieldReference.name}:${qualityFieldReference.type} + const-string v2, "$qIndexMethodName" + invoke-static {p1, p2, v1, v2}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I + move-result p2 + """ + ) + } ?: return VideoQualitySettingsParentFingerprint.toErrorResult() + LegacyVideoIdPatch.injectCall("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V") return PatchResultSuccess() @@ -63,5 +69,11 @@ class VideoQualityBytecodePatch : BytecodePatch( private companion object { const val INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR = "$VIDEO_PATH/VideoQualityPatch;" + + private lateinit var qIndexMethodName: String + + private lateinit var relayFieldReference: FieldReference + private lateinit var qualityFieldReference: FieldReference + } }