From 963fe753b6555d750efdbeed73ba89df060408f8 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 27 Sep 2023 16:09:22 +0400 Subject: [PATCH 1/6] fix(YouTube - Video Id): Fix video id not showing the currently playing video --- .../ReturnYouTubeDislikePatch.kt | 4 +- .../sponsorblock/SponsorBlockBytecodePatch.kt | 5 +-- .../information/VideoInformationPatch.kt | 8 +++- .../youtube/video/videoid/VideoIdPatch.kt | 38 +++++++++++-------- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index 235c0e3f7d..e2462fda79 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -51,9 +51,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( override fun execute(context: BytecodeContext) { // region Inject newVideoLoaded event handler to update dislikes when a new video is loaded. - // This patch needs a few adjustments and lots of testing before it can change to the new video id hook. - // There's a few corner cases and some weirdness when loading new videos (specifically with detecting shorts). - VideoIdPatch.legacyInjectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V") + VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V") // endregion diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt index 0fb4b26572..834be96430 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt @@ -95,11 +95,8 @@ object SponsorBlockBytecodePatch : BytecodePatch( /* * Set current video id. - * - * The new video id hook seems to work without issues, - * but it's easier to keep using this hook as it's well tested and has no known problems. */ - VideoIdPatch.legacyInjectCallBackgroundPlay("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") + VideoIdPatch.injectCallBackgroundPlay("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") /* * Seekbar drawing diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index 4e0a6970e3..25de55ba0f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -109,9 +109,13 @@ object VideoInformationPatch : BytecodePatch( } /* - * Inject call for video id + * Inject call for video ids */ - VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V") + val videoIdMethodDescriptor = "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V" + VideoIdPatch.injectCall(videoIdMethodDescriptor) + VideoIdPatch.injectCallBackgroundPlay(videoIdMethodDescriptor) + VideoIdPatch.injectCallPlayerResponse( + "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoIdPlayerResponse(Ljava/lang/String;)V") /* * Set the video time method diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt index eccc477533..80ad4bc771 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt @@ -64,20 +64,6 @@ object VideoIdPatch : BytecodePatch( } } - /** - * Adds an invoke-static instruction, called with the new id when the video changes. - * - * Called as soon as the player response is parsed, and called before many other hooks are - * updated such as [PlayerTypeHookPatch]. - * - * Supports all videos and functions in all situations. - * - * Be aware, this can be called multiple times for the same video id. - * - * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` - */ - fun injectCall(methodDescriptor: String) = PlayerResponseMethodHookPatch.injectVideoIdHook(methodDescriptor) - /** * Adds an invoke-static instruction, called with the new id when the video changes. * @@ -89,7 +75,7 @@ object VideoIdPatch : BytecodePatch( * * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` */ - fun legacyInjectCall( + fun injectCall( methodDescriptor: String ) = insertMethod.addInstruction( insertIndex++, @@ -106,11 +92,31 @@ object VideoIdPatch : BytecodePatch( * * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` */ - fun legacyInjectCallBackgroundPlay( + fun injectCallBackgroundPlay( methodDescriptor: String ) = backgroundPlaybackMethod.addInstruction( backgroundPlaybackInsertIndex++, // move-result-object offset "invoke-static {v$backgroundPlaybackVideoIdRegister}, $methodDescriptor" ) + + /** + * Adds an invoke-static instruction, called with the video id of every video when loaded. + * Supports all videos and functions in all situations. + * + * This hook is called as soon as the player response is parsed, + * and called before many other hooks are updated such as [PlayerTypeHookPatch]. + * + * Note: The video id returned here may not be the current video that's being played. + * It's common for multiple Shorts to load at once in preparation + * for the user swiping to the next Short. + * + * For most use cases, you probably want to use + * [injectCall] or [injectCallBackgroundPlay] instead. + * + * Be aware, this can be called multiple times for the same video id. + * + * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` + */ + fun injectCallPlayerResponse(methodDescriptor: String) = PlayerResponseMethodHookPatch.injectVideoIdHook(methodDescriptor) } From e77a5d5f5442affeaf89734adad0d92477f001b2 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 27 Sep 2023 19:26:16 +0400 Subject: [PATCH 2/6] comments --- .../app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt index 80ad4bc771..ba2f363a19 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt @@ -103,6 +103,8 @@ object VideoIdPatch : BytecodePatch( * Adds an invoke-static instruction, called with the video id of every video when loaded. * Supports all videos and functions in all situations. * + * Hook is always called off the main thread. + * * This hook is called as soon as the player response is parsed, * and called before many other hooks are updated such as [PlayerTypeHookPatch]. * From b1a061c2a2c32e633dabbef248d7369ebd66da79 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 27 Sep 2023 18:00:38 +0200 Subject: [PATCH 3/6] refactor: Fix naming consistency and simplify code --- .../ReturnYouTubeDislikePatch.kt | 2 +- .../sponsorblock/SponsorBlockBytecodePatch.kt | 2 +- .../misc/fix/playback/SpoofSignaturePatch.kt | 4 +- .../information/VideoInformationPatch.kt | 8 +-- .../PlayerResponseMethodHookPatch.kt | 64 +++++++------------ .../youtube/video/videoid/VideoIdPatch.kt | 25 ++++---- 6 files changed, 45 insertions(+), 60 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index e2462fda79..3ab8e1efaf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -51,7 +51,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( override fun execute(context: BytecodeContext) { // region Inject newVideoLoaded event handler to update dislikes when a new video is loaded. - VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V") + VideoIdPatch.hookVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V") // endregion diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt index 834be96430..a802349a66 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt @@ -96,7 +96,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( /* * Set current video id. */ - VideoIdPatch.injectCallBackgroundPlay("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") + VideoIdPatch.hookBackgroundPlayVideoId("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") /* * Seekbar drawing diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt index 55e6014ba4..2b473f0ba9 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt @@ -88,7 +88,9 @@ object SpoofSignaturePatch : BytecodePatch( ) // Hook the player parameters. - PlayerResponseMethodHookPatch.injectProtoBufferHook("$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;") + PlayerResponseMethodHookPatch.hookProtoBufferParameter( + "$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;" + ) // Force the seekbar time and chapters to always show up. // This is used only if the storyboard spec fetch fails, or when viewing paid videos. diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index 25de55ba0f..2aee32fe05 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -112,10 +112,10 @@ object VideoInformationPatch : BytecodePatch( * Inject call for video ids */ val videoIdMethodDescriptor = "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V" - VideoIdPatch.injectCall(videoIdMethodDescriptor) - VideoIdPatch.injectCallBackgroundPlay(videoIdMethodDescriptor) - VideoIdPatch.injectCallPlayerResponse( - "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoIdPlayerResponse(Ljava/lang/String;)V") + VideoIdPatch.hookVideoId(videoIdMethodDescriptor) + VideoIdPatch.hookBackgroundPlayVideoId(videoIdMethodDescriptor) + VideoIdPatch.hookPlayerResponseVideoId( + "$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;)V") /* * Set the video time method diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt index 53670c37b8..1c986679c2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt @@ -7,66 +7,48 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.misc.fix.playback.SpoofSignaturePatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint -import app.revanced.patches.youtube.video.videoid.VideoIdPatch @Patch( dependencies = [IntegrationsPatch::class], ) object PlayerResponseMethodHookPatch : BytecodePatch( - setOf( - PlayerParameterBuilderFingerprint, - ) + setOf(PlayerParameterBuilderFingerprint) ) { - private const val playerResponseVideoIdParameter = 1 - private const val playerResponseProtoBufferParameter = 3 - /** - * Insert index when adding a video id hook. - */ - private var playerResponseVideoIdInsertIndex = 0 - /** - * Insert index when adding a proto buffer override. - * Must be after all video id hooks in the same method. - */ - private var playerResponseProtoBufferInsertIndex = 0 + private const val VIDEO_ID_PARAMETER = 1 + private const val PROTO_BUFFER_PARAMETER_PARAMETER = 3 + private lateinit var playerResponseMethod: MutableMethod + // Hook insert indices are incremented in the order they're added. + private var videoIdHookInsertIndex = 0 + private var protoBufferParameterHookInsertIndex = 0 + override fun execute(context: BytecodeContext) { + playerResponseMethod = PlayerParameterBuilderFingerprint.result?.mutableMethod + ?: throw PlayerParameterBuilderFingerprint.exception + } - // Hook player parameter. - PlayerParameterBuilderFingerprint.result?.let { - playerResponseMethod = it.mutableMethod - } ?: throw PlayerParameterBuilderFingerprint.exception + fun hookVideoId(methodDescriptor: String) { + playerResponseMethod.addInstruction( + ++videoIdHookInsertIndex, "invoke-static {p$VIDEO_ID_PARAMETER}, $methodDescriptor" + ) + + // TODO: Explain why any video id hook has to precede any protoBufferParameterHook. + protoBufferParameterHookInsertIndex++ } - /** - * Modify the player parameter proto buffer value. - * Used exclusively by [SpoofSignaturePatch]. - */ - fun injectProtoBufferHook(methodDescriptor: String) { + fun hookProtoBufferParameter(methodDescriptor: String) { playerResponseMethod.addInstructions( - playerResponseProtoBufferInsertIndex, + protoBufferParameterHookInsertIndex, """ - invoke-static {p$playerResponseProtoBufferParameter}, $methodDescriptor - move-result-object p$playerResponseProtoBufferParameter + invoke-static {p$PROTO_BUFFER_PARAMETER_PARAMETER}, $methodDescriptor + move-result-object p$PROTO_BUFFER_PARAMETER_PARAMETER """ ) - playerResponseProtoBufferInsertIndex += 2 - } - /** - * Used by [VideoIdPatch]. - */ - internal fun injectVideoIdHook(methodDescriptor: String) { - playerResponseMethod.addInstruction( - // Keep injection calls in the order they're added, - // and all video id hooks run before proto buffer hooks. - playerResponseVideoIdInsertIndex++, - "invoke-static {p$playerResponseVideoIdParameter}, $methodDescriptor" - ) - playerResponseProtoBufferInsertIndex++ + protoBufferParameterHookInsertIndex += 2 } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt index ba2f363a19..980efa6974 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt @@ -26,8 +26,8 @@ object VideoIdPatch : BytecodePatch( ) ) { private var videoIdRegister = 0 - private var insertIndex = 0 - private lateinit var insertMethod: MutableMethod + private var videoIdInsertIndex = 0 + private lateinit var videoIdMethod: MutableMethod private var backgroundPlaybackVideoIdRegister = 0 private var backgroundPlaybackInsertIndex = 0 @@ -52,8 +52,8 @@ object VideoIdPatch : BytecodePatch( } ?: throw VideoIdFingerprint.exception VideoIdFingerprint.setFields { method, index, register -> - insertMethod = method - insertIndex = index + videoIdMethod = method + videoIdInsertIndex = index videoIdRegister = register } @@ -65,7 +65,7 @@ object VideoIdPatch : BytecodePatch( } /** - * Adds an invoke-static instruction, called with the new id when the video changes. + * Hooks the new video id when the video changes. * * Supports all videos (regular videos and Shorts). * @@ -75,10 +75,10 @@ object VideoIdPatch : BytecodePatch( * * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` */ - fun injectCall( + fun hookVideoId( methodDescriptor: String - ) = insertMethod.addInstruction( - insertIndex++, + ) = videoIdMethod.addInstruction( + videoIdInsertIndex++, "invoke-static {v$videoIdRegister}, $methodDescriptor" ) @@ -92,7 +92,7 @@ object VideoIdPatch : BytecodePatch( * * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` */ - fun injectCallBackgroundPlay( + fun hookBackgroundPlayVideoId( methodDescriptor: String ) = backgroundPlaybackMethod.addInstruction( backgroundPlaybackInsertIndex++, // move-result-object offset @@ -100,7 +100,7 @@ object VideoIdPatch : BytecodePatch( ) /** - * Adds an invoke-static instruction, called with the video id of every video when loaded. + * Hooks the video id of every video when loaded. * Supports all videos and functions in all situations. * * Hook is always called off the main thread. @@ -113,12 +113,13 @@ object VideoIdPatch : BytecodePatch( * for the user swiping to the next Short. * * For most use cases, you probably want to use - * [injectCall] or [injectCallBackgroundPlay] instead. + * [hookVideoId] or [hookBackgroundPlayVideoId] instead. * * Be aware, this can be called multiple times for the same video id. * * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` */ - fun injectCallPlayerResponse(methodDescriptor: String) = PlayerResponseMethodHookPatch.injectVideoIdHook(methodDescriptor) + fun hookPlayerResponseVideoId(methodDescriptor: String) = + PlayerResponseMethodHookPatch.hookVideoId(methodDescriptor) } From de5944c6e8fb28a40c3e62c2fb318ff44e310347 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 27 Sep 2023 20:10:52 +0400 Subject: [PATCH 4/6] comments, fix start index (first hook inserted should be at index 0, not index 1). --- .../playerresponse/PlayerResponseMethodHookPatch.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt index 1c986679c2..85258e2359 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt @@ -8,6 +8,7 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch +import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint @Patch( @@ -32,10 +33,16 @@ object PlayerResponseMethodHookPatch : BytecodePatch( fun hookVideoId(methodDescriptor: String) { playerResponseMethod.addInstruction( - ++videoIdHookInsertIndex, "invoke-static {p$VIDEO_ID_PARAMETER}, $methodDescriptor" + videoIdHookInsertIndex++, "invoke-static {p$VIDEO_ID_PARAMETER}, $methodDescriptor" ) - // TODO: Explain why any video id hook has to precede any protoBufferParameterHook. + /** + * Adjust the buffer hook insert index since this video id hook was added before it. + * + * This ensures all video id hooks always run before the buffer hooks, + * so if the buffer hook calls into [VideoInformationPatch] + * it has the correct and updated player response video id. + */ protoBufferParameterHookInsertIndex++ } From bc07f3dbbef5e6cc977d775df0a73aeb5e9d0e49 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 28 Sep 2023 03:34:22 +0200 Subject: [PATCH 5/6] leverage abstraction instead of dependency inversion --- .../misc/fix/playback/SpoofSignaturePatch.kt | 2 +- .../PlayerResponseMethodHookPatch.kt | 57 ++++++++++--------- .../youtube/video/videoid/VideoIdPatch.kt | 7 ++- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt index 2b473f0ba9..0ba824aaeb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt @@ -88,7 +88,7 @@ object SpoofSignaturePatch : BytecodePatch( ) // Hook the player parameters. - PlayerResponseMethodHookPatch.hookProtoBufferParameter( + PlayerResponseMethodHookPatch + PlayerResponseMethodHookPatch.Hook.ProtoBufferParameterBeforeVideoId( "$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt index 85258e2359..e5108e4887 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt @@ -8,54 +8,57 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch -import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint +import java.io.Closeable @Patch( dependencies = [IntegrationsPatch::class], ) -object PlayerResponseMethodHookPatch : BytecodePatch( - setOf(PlayerParameterBuilderFingerprint) -) { +object PlayerResponseMethodHookPatch : + BytecodePatch(setOf(PlayerParameterBuilderFingerprint)), + Closeable, + MutableSet by mutableSetOf() { private const val VIDEO_ID_PARAMETER = 1 private const val PROTO_BUFFER_PARAMETER_PARAMETER = 3 private lateinit var playerResponseMethod: MutableMethod - // Hook insert indices are incremented in the order they're added. - private var videoIdHookInsertIndex = 0 - private var protoBufferParameterHookInsertIndex = 0 - override fun execute(context: BytecodeContext) { playerResponseMethod = PlayerParameterBuilderFingerprint.result?.mutableMethod ?: throw PlayerParameterBuilderFingerprint.exception } - fun hookVideoId(methodDescriptor: String) { - playerResponseMethod.addInstruction( - videoIdHookInsertIndex++, "invoke-static {p$VIDEO_ID_PARAMETER}, $methodDescriptor" + override fun close() { + fun hookVideoId(hook: Hook) = playerResponseMethod.addInstruction( + 0, "invoke-static {p$VIDEO_ID_PARAMETER}, $hook" ) - /** - * Adjust the buffer hook insert index since this video id hook was added before it. - * - * This ensures all video id hooks always run before the buffer hooks, - * so if the buffer hook calls into [VideoInformationPatch] - * it has the correct and updated player response video id. - */ - protoBufferParameterHookInsertIndex++ - } - - fun hookProtoBufferParameter(methodDescriptor: String) { - playerResponseMethod.addInstructions( - protoBufferParameterHookInsertIndex, + fun hookProtoBufferParameter(hook: Hook) = playerResponseMethod.addInstructions( + 0, """ - invoke-static {p$PROTO_BUFFER_PARAMETER_PARAMETER}, $methodDescriptor - move-result-object p$PROTO_BUFFER_PARAMETER_PARAMETER + invoke-static {p$PROTO_BUFFER_PARAMETER_PARAMETER}, $hook + move-result-object p$PROTO_BUFFER_PARAMETER_PARAMETER """ ) - protoBufferParameterHookInsertIndex += 2 + // Reverse the order in order to preserve insertion order of the hooks. + val beforeVideoIdHooks = filterIsInstance().asReversed() + val videoIdHooks = filterIsInstance().asReversed() + val protoBufferParameterHooks = filterIsInstance().asReversed() + + // Add the hooks in this specific order as they insert instructions at the beginning of the method. + protoBufferParameterHooks.forEach(::hookProtoBufferParameter) + videoIdHooks.forEach(::hookVideoId) + beforeVideoIdHooks.forEach(::hookProtoBufferParameter) + } + + internal abstract class Hook(private val methodDescriptor: String) { + internal class VideoId(methodDescriptor: String) : Hook(methodDescriptor) + + internal class ProtoBufferParameter(methodDescriptor: String) : Hook(methodDescriptor) + internal class ProtoBufferParameterBeforeVideoId(methodDescriptor: String) : Hook(methodDescriptor) + + override fun toString() = methodDescriptor } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt index 980efa6974..57df0c97f1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt @@ -119,7 +119,10 @@ object VideoIdPatch : BytecodePatch( * * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` */ - fun hookPlayerResponseVideoId(methodDescriptor: String) = - PlayerResponseMethodHookPatch.hookVideoId(methodDescriptor) + fun hookPlayerResponseVideoId(methodDescriptor: String) { + PlayerResponseMethodHookPatch + PlayerResponseMethodHookPatch.Hook.VideoId( + methodDescriptor + ) + } } From 6c18c41c1322265f70de6c748b718433b75aae26 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:58:17 +0400 Subject: [PATCH 6/6] fix: fix ordering --- .../patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt | 2 +- .../video/playerresponse/PlayerResponseMethodHookPatch.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt index 0ba824aaeb..2f594c7aa3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt @@ -88,7 +88,7 @@ object SpoofSignaturePatch : BytecodePatch( ) // Hook the player parameters. - PlayerResponseMethodHookPatch + PlayerResponseMethodHookPatch.Hook.ProtoBufferParameterBeforeVideoId( + PlayerResponseMethodHookPatch + PlayerResponseMethodHookPatch.Hook.ProtoBufferParameter( "$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt index e5108e4887..a08531bb1c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt @@ -44,10 +44,10 @@ object PlayerResponseMethodHookPatch : // Reverse the order in order to preserve insertion order of the hooks. val beforeVideoIdHooks = filterIsInstance().asReversed() val videoIdHooks = filterIsInstance().asReversed() - val protoBufferParameterHooks = filterIsInstance().asReversed() + val afterVideoIdHooks = filterIsInstance().asReversed() // Add the hooks in this specific order as they insert instructions at the beginning of the method. - protoBufferParameterHooks.forEach(::hookProtoBufferParameter) + afterVideoIdHooks.forEach(::hookProtoBufferParameter) videoIdHooks.forEach(::hookVideoId) beforeVideoIdHooks.forEach(::hookProtoBufferParameter) }