fix(YouTube - Downloads): Use new task context (#2841)

This commit is contained in:
LisoUseInAIKyrios 2024-03-08 09:09:15 +04:00 committed by GitHub
parent f24adf753e
commit 6d88cb49ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 142 additions and 58 deletions

View file

@ -1748,6 +1748,7 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I
public static final fun indexOfFirstWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)I public static final fun indexOfFirstWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
public static final fun resultOrThrow (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;
public static final fun returnEarly (Ljava/util/List;Z)V public static final fun returnEarly (Ljava/util/List;Z)V
public static synthetic fun returnEarly$default (Ljava/util/List;ZILjava/lang/Object;)V public static synthetic fun returnEarly$default (Ljava/util/List;ZILjava/lang/Object;)V
public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V

View file

@ -64,8 +64,8 @@ abstract class BaseIntegrationsPatch(
method.addInstruction( method.addInstruction(
0, 0,
"sput-object v$contextRegister, " + "invoke-static/range { v$contextRegister .. v$contextRegister }, " +
"$integrationsDescriptor->context:Landroid/content/Context;", "$integrationsDescriptor->setContext(Landroid/content/Context;)V",
) )
} ?: throw PatchException("Could not find hook target fingerprint.") } ?: throw PatchException("Could not find hook target fingerprint.")
} }

View file

@ -1,16 +1,18 @@
package app.revanced.patches.youtube.interaction.downloads package app.revanced.patches.youtube.interaction.downloads
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.interaction.downloads.fingerprints.DownloadActionCommandResolverFingerprint
import app.revanced.patches.youtube.interaction.downloads.fingerprints.DownloadButtonActionFingerprint import app.revanced.patches.youtube.interaction.downloads.fingerprints.DownloadActionCommandResolverParentFingerprint
import app.revanced.patches.youtube.interaction.downloads.fingerprints.LegacyDownloadCommandResolverFingerprint
import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch
import app.revanced.patches.youtube.shared.fingerprints.MainActivityFingerprint
import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.util.exception import app.revanced.util.resultOrThrow
@Patch( @Patch(
name = "Downloads", name = "Downloads",
@ -39,8 +41,10 @@ import app.revanced.util.exception
@Suppress("unused") @Suppress("unused")
object DownloadsPatch : BytecodePatch( object DownloadsPatch : BytecodePatch(
setOf( setOf(
DownloadButtonActionFingerprint, DownloadActionCommandResolverParentFingerprint,
), LegacyDownloadCommandResolverFingerprint,
MainActivityFingerprint
)
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DownloadsPatch;" private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DownloadsPatch;"
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;" private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
@ -49,19 +53,46 @@ object DownloadsPatch : BytecodePatch(
PlayerControlsBytecodePatch.initializeControl("$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V") PlayerControlsBytecodePatch.initializeControl("$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$BUTTON_DESCRIPTOR->changeVisibility(Z)V") PlayerControlsBytecodePatch.injectVisibilityCheckCall("$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
DownloadButtonActionFingerprint.result?.let { // Main activity is used to launch downloader intent.
it.mutableMethod.apply { MainActivityFingerprint.resultOrThrow().mutableMethod.apply {
addInstructionsWithLabels( addInstruction(
2, implementation!!.instructions.lastIndex,
""" "invoke-static { p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V"
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppDownloadButtonOnClick()Z )
move-result v0 }
if-eqz v0, :show_dialog
return-void val commonInstructions = """
""", move-result v0
ExternalLabel("show_dialog", getInstruction(2)), if-eqz v0, :show_native_downloader
return-void
:show_native_downloader
nop
"""
DownloadActionCommandResolverFingerprint.resolve(context,
DownloadActionCommandResolverParentFingerprint.resultOrThrow().classDef)
DownloadActionCommandResolverFingerprint.resultOrThrow().mutableMethod.apply {
addInstructionsWithLabels(
0,
"""
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppDownloadButtonOnClick()Z
$commonInstructions
"""
)
}
// Legacy fingerprint is used for old spoofed versions,
// or if download playlist is pressed on any version.
// Downloading playlists is not yet supported,
// as the code this hooks does not easily expost the playlist id.
LegacyDownloadCommandResolverFingerprint.resultOrThrow().mutableMethod.apply {
addInstructionsWithLabels(
0,
"""
invoke-static/range {p1 .. p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppDownloadPlaylistLegacyOnClick(Ljava/lang/String;)Z
$commonInstructions
"""
) )
} }
} ?: throw DownloadButtonActionFingerprint.exception
} }
} }

View file

@ -31,8 +31,8 @@ internal object DownloadsResourcePatch : ResourcePatch() {
sorting = Sorting.UNSORTED, sorting = Sorting.UNSORTED,
preferences = setOf( preferences = setOf(
SwitchPreference("revanced_external_downloader"), SwitchPreference("revanced_external_downloader"),
SwitchPreference("revanced_external_downloader_action_button"),
TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT), TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT),
SwitchPreference("revanced_use_in_app_download_button"),
), ),
), ),
) )

View file

@ -0,0 +1,14 @@
package app.revanced.patches.youtube.interaction.downloads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Resolves to the class found in [DownloadActionCommandResolverParentFingerprint].
*/
internal object DownloadActionCommandResolverFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("L", "Ljava/util/Map;")
)

View file

@ -0,0 +1,17 @@
package app.revanced.patches.youtube.interaction.downloads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object DownloadActionCommandResolverParentFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("L", "L"),
strings = listOf(
// Strings are not unique and found in other methods.
"com.google.android.libraries.youtube.logging.interaction_logger",
"Unknown command"
),
literalSupplier = { 16 }
)

View file

@ -1,7 +0,0 @@
package app.revanced.patches.youtube.interaction.downloads.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object DownloadButtonActionFingerprint : MethodFingerprint(
strings = listOf("offline/get_download_action"),
)

View file

@ -0,0 +1,24 @@
package app.revanced.patches.youtube.interaction.downloads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* For spoofing to older versions. Also called if download playlist is pressed for any version.
*/
internal object LegacyDownloadCommandResolverFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("Ljava/lang/String;", "Ljava/lang/String;", "L", "L"),
strings = listOf(""),
opcodes = listOf(
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
)
)

View file

@ -32,6 +32,7 @@ import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import app.revanced.util.exception import app.revanced.util.exception
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@ -88,8 +89,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
private const val FILTER_CLASS_DESCRIPTOR = private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;" "Lapp/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;"
private fun MethodFingerprint.resultOrThrow() = result ?: throw exception
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded. // region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.

View file

@ -23,7 +23,7 @@ import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.reques
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception import app.revanced.util.resultOrThrow
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.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
@ -144,11 +144,8 @@ object AlternativeThumbnailsPatch : BytecodePatch(
NonInteractivePreference("revanced_alt_thumbnail_stills_about"), NonInteractivePreference("revanced_alt_thumbnail_stills_about"),
) )
fun MethodFingerprint.getResultOrThrow() =
result ?: throw exception
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) = fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
also { resolve(context, fingerprint.getResultOrThrow().classDef) }.getResultOrThrow() also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
fun MethodFingerprint.resolveAndLetMutableMethod( fun MethodFingerprint.resolveAndLetMutableMethod(
fingerprint: MethodFingerprint, fingerprint: MethodFingerprint,
@ -172,7 +169,7 @@ object AlternativeThumbnailsPatch : BytecodePatch(
// 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.
RequestFingerprint.getResultOrThrow().apply { RequestFingerprint.resultOrThrow().apply {
// The url is the only string field that is set inside the constructor. // The url is the only string field that is set inside the constructor.
val urlFieldInstruction = mutableMethod.getInstructions().first { val urlFieldInstruction = mutableMethod.getInstructions().first {
if (it.opcode != Opcode.IPUT_OBJECT) return@first false if (it.opcode != Opcode.IPUT_OBJECT) return@first false

View file

@ -3,30 +3,31 @@ package app.revanced.patches.youtube.misc.playeroverlay
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.playeroverlay.fingerprint.PlayerOverlaysOnFinishInflateFingerprint import app.revanced.patches.youtube.misc.playeroverlay.fingerprint.PlayerOverlaysOnFinishInflateFingerprint
import app.revanced.util.exception
@Patch( @Patch(
description = "Hook for adding custom overlays to the video player.", description = "Hook for the video player overlay",
dependencies = [IntegrationsPatch::class], dependencies = [IntegrationsPatch::class],
compatiblePackages = [
CompatiblePackage("com.google.android.youtube", [
"18.32.39"
])
]
) )
/**
* Edit: This patch is not in use and may not work.
*/
@Suppress("unused") @Suppress("unused")
object PlayerOverlaysHookPatch : BytecodePatch( // TODO: delete this unused outdated patch and its integration code. object PlayerOverlaysHookPatch : BytecodePatch(
setOf(PlayerOverlaysOnFinishInflateFingerprint) setOf(PlayerOverlaysOnFinishInflateFingerprint)
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch;"
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// hook YouTubePlayerOverlaysLayout.onFinishInflate() PlayerOverlaysOnFinishInflateFingerprint.result?.mutableMethod?.apply {
val method = PlayerOverlaysOnFinishInflateFingerprint.result!!.mutableMethod addInstruction(
method.addInstruction( implementation!!.instructions.lastIndex,
method.implementation!!.instructions.size - 2, "invoke-static { p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->playerOverlayInflated(Landroid/view/ViewGroup;)V"
"invoke-static { p0 }, Lapp/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch;->YouTubePlayerOverlaysLayout_onFinishInflateHook(Ljava/lang/Object;)V"
) )
} ?: throw PlayerOverlaysOnFinishInflateFingerprint.exception
} }
} }

View file

@ -1,10 +1,14 @@
package app.revanced.patches.youtube.misc.playeroverlay.fingerprint package app.revanced.patches.youtube.misc.playeroverlay.fingerprint
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object PlayerOverlaysOnFinishInflateFingerprint : MethodFingerprint( internal object PlayerOverlaysOnFinishInflateFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("YouTubePlayerOverlaysLayout;") && methodDef.name == "onFinishInflate" methodDef.definingClass.endsWith("/YouTubePlayerOverlaysLayout;")
} && methodDef.name == "onFinishInflate"
},
) )

View file

@ -15,6 +15,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
import com.android.tools.smali.dexlib2.iface.reference.Reference import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.util.MethodUtil
fun MethodFingerprint.resultOrThrow() = result ?: throw exception
/** /**
* The [PatchException] of failing to resolve a [MethodFingerprint]. * The [PatchException] of failing to resolve a [MethodFingerprint].
* *

View file

@ -232,12 +232,12 @@
<string name="revanced_external_downloader_title">Show external download button</string> <string name="revanced_external_downloader_title">Show external download button</string>
<string name="revanced_external_downloader_summary_on">Download button shown in player</string> <string name="revanced_external_downloader_summary_on">Download button shown in player</string>
<string name="revanced_external_downloader_summary_off">Download button not shown in player</string> <string name="revanced_external_downloader_summary_off">Download button not shown in player</string>
<string name="revanced_external_downloader_action_button_title">Override download action button</string>
<string name="revanced_external_downloader_action_button_summary_on">Download button opens your external downloader</string>
<string name="revanced_external_downloader_action_button_summary_off">Download button opens the native in-app downloader</string>
<string name="revanced_external_downloader_name_title">Downloader package name</string> <string name="revanced_external_downloader_name_title">Downloader package name</string>
<string name="revanced_external_downloader_name_summary">Package name of your installed external downloader app, such as NewPipe or Seal</string> <string name="revanced_external_downloader_name_summary">Package name of your installed external downloader app, such as NewPipe or Seal</string>
<string name="revanced_external_downloader_not_installed_warning">%s is not installed. Please install it.</string> <string name="revanced_external_downloader_not_installed_warning">%s is not installed. Please install it.</string>
<string name="revanced_use_in_app_download_button_title">Use in-app download button</string>
<string name="revanced_use_in_app_download_button_summary_on">Button will launch the external downloader</string>
<string name="revanced_use_in_app_download_button_summary_off">Button will launch the native in-app downloader</string>
</patch> </patch>
<patch id="interaction.seekbar.DisablePreciseSeekingGesturePatch"> <patch id="interaction.seekbar.DisablePreciseSeekingGesturePatch">
<string name="revanced_disable_precise_seeking_gesture_title">Disable precise seeking gesture</string> <string name="revanced_disable_precise_seeking_gesture_title">Disable precise seeking gesture</string>