feat(youtube): support version 18.23.35 (#2461)

Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
LisoUseInAIKyrios
2023-07-08 01:02:32 +02:00
committed by GitHub
co-authored by oSumAtrIX
parent 67294c76cd
commit 34514b04f1
81 changed files with 499 additions and 225 deletions
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.autorepeat.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoRepeatCompatibility
@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.misc.bottomsheet.hook.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.video.videoqualitymenu.patch.OldVideoQualityMenuResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import org.jf.dexlib2.AccessFlags
object CreateBottomSheetFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"),
returnType = "Landroid/widget/LinearLayout;",
literal = OldVideoQualityMenuResourcePatch.bottomSheetMargins
)
@@ -0,0 +1,43 @@
package app.revanced.patches.youtube.misc.bottomsheet.hook.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.youtube.misc.bottomsheet.hook.fingerprints.CreateBottomSheetFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@DependsOn([IntegrationsPatch::class])
class BottomSheetHookPatch : BytecodePatch(
listOf(CreateBottomSheetFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
CreateBottomSheetFingerprint.result?.let {
it.mutableMethod.apply {
val returnLinearLayoutIndex = implementation!!.instructions.lastIndex
val linearLayoutRegister = getInstruction<OneRegisterInstruction>(returnLinearLayoutIndex).registerA
addHook = { classDescriptor ->
addInstruction(
returnLinearLayoutIndex,
"invoke-static { v$linearLayoutRegister }, " +
"${classDescriptor}->" +
"onFlyoutMenuCreate(Landroid/widget/LinearLayout;)V"
)
}
}
} ?: return CreateBottomSheetFingerprint.toErrorResult()
return PatchResultSuccess()
}
internal companion object {
internal lateinit var addHook: (String) -> Unit
private set
}
}
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class FixBackToExitGestureCompatibility
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.fix.playback.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class ClientSpoofCompatibility
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.integrations.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class IntegrationsCompatibility
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.links.open.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class OpenLinksExternallyCompatibility
@@ -1,25 +0,0 @@
package app.revanced.patches.youtube.misc.litho.filter.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object ProtobufBufferFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.IGET_OBJECT, // References the field required below.
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
Opcode.IF_NEZ,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CHECK_CAST, // Casts the referenced field to a specific type that stores the protobuf buffer.
Opcode.INVOKE_VIRTUAL
)
)
@@ -0,0 +1,18 @@
package app.revanced.patches.youtube.misc.litho.filter.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 ProtobufBufferReferenceFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("I", "Ljava/nio/ByteBuffer;"),
opcodes = listOf(
Opcode.IPUT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.SUB_INT_2ADDR
)
)
@@ -4,50 +4,110 @@ import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.or
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.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.*
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.immutable.ImmutableField
import java.io.Closeable
@DependsOn([IntegrationsPatch::class])
@Description("Hooks the method which parses the bytes into a ComponentContext to filter components.")
@Version("0.0.1")
class LithoFilterPatch : BytecodePatch(
listOf(ComponentContextParserFingerprint, LithoFilterFingerprint)
listOf(ComponentContextParserFingerprint, LithoFilterFingerprint, ProtobufBufferReferenceFingerprint)
), Closeable {
/**
* The following patch inserts a hook into the method that parses the bytes into a ComponentContext.
* This method contains a StringBuilder object that represents the pathBuilder of the component.
* The pathBuilder is used to filter components by their path.
*
* Additionally, the method contains a reference to the components identifier.
* The identifier is used to filter components by their identifier.
*
* In addition to that, a static field is added to the class of this method. (See protobufBufferField).
* This field holds a reference to the protobuf buffer object.
* The field is being set in another method that holds a reference to the protobuf buffer object.
* The object contains a large byte array that represents the component tree.
* This byte array is searched for strings that indicate the current component.
*
* The following pseudo code shows how the patch works:
*
* class ComponentContextParser {
* public static ByteBuffer buffer; // Inserted by this patch.
*
* public ComponentContext parseBytesToComponentContext(...) {
* ...
* if (filter(identifier, pathBuilder, buffer)); // Inserted by this patch.
* return emptyComponent;
* ...
* }
* }
*
* class SomeOtherClass {
* // Called before ComponentContextParser.parseBytesToComponentContext method.
* public void someOtherMethod(ByteBuffer byteBuffer) {
* ComponentContextParser.buffer = byteBuffer; // Inserted by this patch.
* ...
* }
* }
*/
override fun execute(context: BytecodeContext): PatchResult {
ComponentContextParserFingerprint.result?.also {
arrayOf(
EmptyComponentBuilderFingerprint,
ReadComponentIdentifierFingerprint,
ProtobufBufferFingerprint
ReadComponentIdentifierFingerprint
).forEach { fingerprint ->
if (fingerprint.resolve(context, it.mutableMethod, it.mutableClass)) return@forEach
return fingerprint.toErrorResult()
}
}?.let { result ->
}?.let { bytesToComponentContextMethod ->
// region Add a static field that holds a reference to the protobuf buffer object.
val protobufBufferField = ImmutableField(
bytesToComponentContextMethod.mutableClass.type,
"buffer",
"Ljava/nio/ByteBuffer;",
AccessFlags.PUBLIC or AccessFlags.STATIC,
null,
null,
null
).toMutable()
bytesToComponentContextMethod.mutableClass.staticFields.add(protobufBufferField)
// Set the field with the reference to the protobuf buffer object.
ProtobufBufferReferenceFingerprint.result
?.mutableMethod?.addInstruction(0, "sput-object p2, $protobufBufferField")
?: return ProtobufBufferReferenceFingerprint.toErrorResult()
// endregion
// region Hook the method that parses bytes into a ComponentContext.
val builderMethodIndex = EmptyComponentBuilderFingerprint.patternScanEndIndex
val emptyComponentFieldIndex = builderMethodIndex + 2
result.mutableMethod.apply {
val insertHookIndex = result.scanResult.patternScanResult!!.endIndex
bytesToComponentContextMethod.mutableMethod.apply {
val insertHookIndex = bytesToComponentContextMethod.scanResult.patternScanResult!!.endIndex
// region Get free registers that this patch uses
// region Get free registers that this patch uses.
// Registers are overwritten right after they are used in this patch, therefore free to clobber.
val freeRegistersInstruction = getInstruction<FiveRegisterInstruction>(insertHookIndex - 2)
@@ -64,7 +124,7 @@ class LithoFilterPatch : BytecodePatch(
// endregion
// region Get references that this patch needs
// region Get references that this patch needs.
val builderMethodDescriptor = getInstruction(builderMethodIndex).descriptor
val emptyComponentFieldDescriptor = getInstruction(emptyComponentFieldIndex).descriptor
@@ -72,34 +132,18 @@ class LithoFilterPatch : BytecodePatch(
val identifierRegister =
getInstruction<OneRegisterInstruction>(ReadComponentIdentifierFingerprint.patternScanEndIndex).registerA
// Parameter that holds a ref to a type with a field that ref the protobuf buffer object.
val protobufParameterNumber = 3
// Get the field that stores an protobuf buffer required below.
val protobufBufferRefTypeRefFieldDescriptor =
getInstruction(ProtobufBufferFingerprint.patternScanStartIndex).descriptor
val protobufBufferRefTypeDescriptor =
getInstruction(ProtobufBufferFingerprint.patternScanEndIndex - 1).descriptor
val protobufBufferFieldDescriptor = "$protobufBufferRefTypeDescriptor->b:Ljava/nio/ByteBuffer;"
// endregion
// region Patch the method
// region Patch the method.
// Insert the instructions that are responsible
// to return an EmptyComponent instead of the original component if the filter method returns false.
addInstructionsWithLabels(
insertHookIndex,
"""
# Get the protobuf buffer object.
move-object/from16 v$free1, p$protobufParameterNumber
iget-object v$free1, v$free1, $protobufBufferRefTypeRefFieldDescriptor
check-cast v$free1, $protobufBufferRefTypeDescriptor
# Register "free" now holds the protobuf buffer object
# Register "free1" holds the protobuf buffer object
iget-object v$free1, v$free1, $protobufBufferFieldDescriptor
sget-object v$free1, $protobufBufferField
# Invoke the filter method.
@@ -119,6 +163,8 @@ class LithoFilterPatch : BytecodePatch(
)
// endregion
}
// endregion
} ?: return ComponentContextParserFingerprint.toErrorResult()
LithoFilterFingerprint.result?.mutableMethod?.apply {
@@ -150,9 +196,6 @@ class LithoFilterPatch : BytecodePatch(
private val MethodFingerprint.patternScanEndIndex
get() = patternScanResult.endIndex
private val MethodFingerprint.patternScanStartIndex
get() = patternScanResult.startIndex
private val Instruction.descriptor
get() = (this as ReferenceInstruction).reference.toString()
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.microg.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class MicroGPatchCompatibility
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.minimizedplayback.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class MinimizedPlaybackCompatibility
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object MinimizedPlaybackSettingsFingerprint : MethodFingerprint(
returnType = "L",
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
opcodes = listOf(
@@ -8,7 +8,8 @@ import org.jf.dexlib2.AccessFlags
* Class fingerprint for [MinimizedPlaybackSettingsFingerprint]
*/
object MinimizedPlaybackSettingsParentFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("Landroid/content/Context;", "Landroid/support/v4/media/session/MediaSessionCompat"),
strings = listOf("sessionToken must not be null")
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "I",
parameters = listOf(),
strings = listOf("BiometricManager", "Failure in canAuthenticate(). FingerprintManager was null.")
)
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.playercontrols.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerControlsCompatibility
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.playeroverlay.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerOverlaysHookCompatibility
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.playertype.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerTypeHookCompatibility
@@ -4,6 +4,6 @@ import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
// TODO: delete this
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class CustomVideoBufferCompatibility