This commit is contained in:
inotia00
2023-01-10 04:30:54 +09:00
parent 1b83a30a56
commit 7db88c2dc8
77 changed files with 807 additions and 663 deletions

View File

@ -6,18 +6,11 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object StartVideoInformerFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L", "L", "L"), listOf(
Opcode.INVOKE_STATIC,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.IF_EQZ,
Opcode.CONST_STRING,
Opcode.INVOKE_INTERFACE,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
)
Opcode.RETURN_VOID,
),
strings = listOf("pc")
)

View File

@ -6,7 +6,10 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object SubtitleTrackFingerprint : MethodFingerprint(
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
opcodes = listOf(
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,

View File

@ -7,13 +7,12 @@ import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.layout.general.autocaptions.bytecode.fingerprints.*
import app.revanced.shared.annotation.YouTubeCompatibility
import app.revanced.shared.extensions.toErrorResult
import app.revanced.shared.fingerprints.SubtitleButtonControllerFingerprint
import app.revanced.shared.util.integrations.Constants.GENERAL_LAYOUT
@ -32,8 +31,8 @@ class AutoCaptionsBytecodePatch : BytecodePatch(
StartVideoInformerFingerprint.toPatch(Status.DISABLED),
SubtitleButtonControllerFingerprint.toPatch(Status.ENABLED)
).forEach { (fingerprint, status) ->
with(fingerprint.result ?: return PatchResultError("Failed to find ${fingerprint.name} method.")) {
mutableMethod.addInstructions(
with(fingerprint.result?.mutableMethod ?: return fingerprint.toErrorResult()) {
addInstructions(
0,
"""
const/4 v0, ${status.value}
@ -43,19 +42,19 @@ class AutoCaptionsBytecodePatch : BytecodePatch(
}
}
val subtitleTrackMethod = SubtitleTrackFingerprint.result!!.mutableMethod
subtitleTrackMethod.addInstructions(
0, """
invoke-static {}, $GENERAL_LAYOUT->hideAutoCaptions()Z
move-result v0
if-eqz v0, :auto_captions_shown
sget-boolean v0, $GENERAL_LAYOUT->captionsButtonStatus:Z
if-nez v0, :auto_captions_shown
const/4 v0, 0x1
return v0
""", listOf(ExternalLabel("auto_captions_shown", subtitleTrackMethod.instruction(0)))
)
SubtitleTrackFingerprint.result?.mutableMethod?.let {
it.addInstructions(
0, """
invoke-static {}, $GENERAL_LAYOUT->hideAutoCaptions()Z
move-result v0
if-eqz v0, :auto_captions_shown
sget-boolean v0, $GENERAL_LAYOUT->captionsButtonStatus:Z
if-nez v0, :auto_captions_shown
const/4 v0, 0x1
return v0
""", listOf(ExternalLabel("auto_captions_shown", it.instruction(0)))
)
} ?: return SubtitleTrackFingerprint.toErrorResult()
return PatchResultSuccess()
}

View File

@ -5,8 +5,8 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object EngagementPanelControllerFingerprint : MethodFingerprint(
"L",
AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "L",
access = AccessFlags.PRIVATE or AccessFlags.FINAL,
strings = listOf(
"EngagementPanelController: cannot show EngagementPanel before EngagementPanelController.init() has been called.",
"[EngagementPanel] Cannot show EngagementPanel before EngagementPanelController.init() has been called."

View File

@ -11,6 +11,7 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.layout.general.autopopuppanels.bytecode.fingerprints.EngagementPanelControllerFingerprint
import app.revanced.shared.annotation.YouTubeCompatibility
import app.revanced.shared.extensions.toErrorResult
import app.revanced.shared.util.integrations.Constants.GENERAL_LAYOUT
@Name("hide-auto-player-popup-panels-bytecode-patch")
@ -22,18 +23,19 @@ class PlayerPopupPanelsBytecodePatch : BytecodePatch(
)
) {
override fun execute(context: BytecodeContext): PatchResult {
val engagementPanelControllerMethod = EngagementPanelControllerFingerprint.result!!.mutableMethod
engagementPanelControllerMethod.addInstructions(
0, """
invoke-static { }, $GENERAL_LAYOUT->hideAutoPlayerPopupPanels()Z
move-result v0
if-eqz v0, :player_popup_panels_shown
if-eqz p4, :player_popup_panels_shown
const/4 v0, 0x0
return-object v0
""", listOf(ExternalLabel("player_popup_panels_shown", engagementPanelControllerMethod.instruction(0)))
)
EngagementPanelControllerFingerprint.result?.mutableMethod?.let {
it.addInstructions(
0, """
invoke-static {}, $GENERAL_LAYOUT->hideAutoPlayerPopupPanels()Z
move-result v0
if-eqz v0, :player_popup_panels_shown
if-eqz p4, :player_popup_panels_shown
const/4 v0, 0x0
return-object v0
""", listOf(ExternalLabel("player_popup_panels_shown", it.instruction(0)))
)
} ?: return EngagementPanelControllerFingerprint.toErrorResult()
return PatchResultSuccess()
}

View File

@ -12,7 +12,10 @@ import org.jf.dexlib2.Opcode
@YouTubeCompatibility
@Version("0.0.1")
object CreateMixPlaylistFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L", "L", "L"), listOf(
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L", "L", "L", "L", "L", "L", "L"),
opcodes = listOf(
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_VIRTUAL,

View File

@ -21,9 +21,9 @@ object FourthCreateMixPlaylistFingerprint : MethodFingerprint(
Opcode.CHECK_CAST
),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.abclistmenuitemLabelId
methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal &&
(it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.abclistmenuitemLabelId
} == true
}
)

View File

@ -12,7 +12,10 @@ import org.jf.dexlib2.Opcode
@YouTubeCompatibility
@Version("0.0.1")
object SecondCreateMixPlaylistFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L", "L"), listOf(
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L", "L", "L", "L", "L", "L"),
opcodes = listOf(
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_VIRTUAL,

View File

@ -21,9 +21,9 @@ object ThirdCreateMixPlaylistFingerprint : MethodFingerprint(
Opcode.IPUT_OBJECT
),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.bottompaneloverlaytextLabelId
methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal &&
(it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.bottompaneloverlaytextLabelId
} == true
}
)

View File

@ -4,13 +4,14 @@ import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
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
import app.revanced.patches.youtube.layout.general.mixplaylists.bytecode.fingerprints.*
import app.revanced.shared.annotation.YouTubeCompatibility
import app.revanced.shared.extensions.injectHideCall
import app.revanced.shared.extensions.toErrorResult
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
@ -29,34 +30,41 @@ class MixPlaylistsBytecodePatch : BytecodePatch(
) {
override fun execute(context: BytecodeContext): PatchResult {
arrayOf(CreateMixPlaylistFingerprint, SecondCreateMixPlaylistFingerprint).forEach(::addHook)
ThirdCreateMixPlaylistFingerprint.hookMixPlaylists(true)
FourthCreateMixPlaylistFingerprint.hookMixPlaylists(false)
arrayOf(
CreateMixPlaylistFingerprint,
SecondCreateMixPlaylistFingerprint
).map {
it.result ?: return it.toErrorResult()
}.forEach {
it.addHook()
}
arrayOf(
ThirdCreateMixPlaylistFingerprint to true,
FourthCreateMixPlaylistFingerprint to false
).map { (fingerprint, boolean) ->
fingerprint.result?.hookMixPlaylists(boolean) ?: return fingerprint.toErrorResult()
}
return PatchResultSuccess()
}
private fun addHook(fingerprint: MethodFingerprint) {
with (fingerprint.result!!) {
val insertIndex = scanResult.patternScanResult!!.endIndex - 3
private fun MethodFingerprintResult.addHook() {
val insertIndex = scanResult.patternScanResult!!.endIndex - 3
val register = (mutableMethod.instruction(insertIndex - 2) as OneRegisterInstruction).registerA
val register = (mutableMethod.instruction(insertIndex - 2) as OneRegisterInstruction).registerA
mutableMethod.implementation!!.injectHideCall(insertIndex, register, "layout/GeneralLayoutPatch", "hideMixPlaylists")
}
mutableMethod.implementation!!.injectHideCall(insertIndex, register, "layout/GeneralLayoutPatch", "hideMixPlaylists")
}
fun MethodFingerprint.hookMixPlaylists(isThirdFingerprint: Boolean) {
private fun MethodFingerprintResult.hookMixPlaylists(isThirdFingerprint: Boolean) {
fun getRegister(instruction: Instruction): Int {
if (isThirdFingerprint) return (instruction as TwoRegisterInstruction).registerA
return (instruction as Instruction21c).registerA
if (isThirdFingerprint) return (instruction as TwoRegisterInstruction).registerA
return (instruction as Instruction21c).registerA
}
with(this.result!!) {
val endIndex = scanResult.patternScanResult!!.endIndex
val instruction = method.implementation!!.instructions.elementAt(endIndex)
val register = getRegister(instruction)
val endIndex = scanResult.patternScanResult!!.endIndex
val instruction = method.implementation!!.instructions.elementAt(endIndex)
val register = getRegister(instruction)
mutableMethod.implementation!!.injectHideCall(endIndex, register, "layout/GeneralLayoutPatch", "hideMixPlaylists")
}
mutableMethod.implementation!!.injectHideCall(endIndex, register, "layout/GeneralLayoutPatch", "hideMixPlaylists")
}
}

View File

@ -19,12 +19,12 @@ object AccountSwitcherAccessibilityLabelFingerprint : MethodFingerprint(
Opcode.NEW_ARRAY,
Opcode.CONST_4,
Opcode.APUT_OBJECT,
Opcode.CONST,
Opcode.CONST
),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.accountSwitcherAccessibilityLabelId
methodDef.implementation?.instructions?.any { it ->
it.opcode.ordinal == Opcode.CONST.ordinal &&
(it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.accountSwitcherAccessibilityLabelId
} == true
}
)

View File

@ -10,6 +10,7 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patches.youtube.layout.general.personalinformation.bytecode.fingerprints.AccountSwitcherAccessibilityLabelFingerprint
import app.revanced.shared.annotation.YouTubeCompatibility
import app.revanced.shared.extensions.toErrorResult
import app.revanced.shared.util.integrations.Constants.GENERAL_LAYOUT
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@ -22,23 +23,20 @@ class HideEmailAddressBytecodePatch : BytecodePatch(
)
) {
override fun execute(context: BytecodeContext): PatchResult {
val accountSwitcherAccessibilityLabelResult = AccountSwitcherAccessibilityLabelFingerprint.result!!
val accountSwitcherAccessibilityLabelMethod = accountSwitcherAccessibilityLabelResult.mutableMethod
val setVisibilityConstIndex =
accountSwitcherAccessibilityLabelResult.scanResult.patternScanResult!!.endIndex
AccountSwitcherAccessibilityLabelFingerprint.result?.let {
with (it.mutableMethod) {
val insertIndex = it.scanResult.patternScanResult!!.endIndex
val register = (instruction(insertIndex - 2) as OneRegisterInstruction).registerA
val setVisibilityConstRegister = (
accountSwitcherAccessibilityLabelMethod.instruction
(setVisibilityConstIndex - 2) as OneRegisterInstruction
).registerA
accountSwitcherAccessibilityLabelMethod.addInstructions(
setVisibilityConstIndex, """
invoke-static {v$setVisibilityConstRegister}, $GENERAL_LAYOUT->hideEmailAddress(I)I
move-result v$setVisibilityConstRegister
"""
)
addInstructions(
insertIndex, """
invoke-static {v$register}, $GENERAL_LAYOUT->hideEmailAddress(I)I
move-result v$register
"""
)
}
} ?: return AccountSwitcherAccessibilityLabelFingerprint.toErrorResult()
return PatchResultSuccess()
}

View File

@ -12,9 +12,9 @@ object PivotBarCreateButtonViewFingerprint : MethodFingerprint(
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Z"),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.imageOnlyTabId
methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal &&
(it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.imageOnlyTabId
} == true
}
)

View File

@ -17,9 +17,9 @@ object PivotBarFingerprint : MethodFingerprint(
),
customFingerprint = { methodDef ->
methodDef.definingClass == "Lcom/google/android/apps/youtube/app/ui/pivotbar/PivotBar;" &&
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.imageWithTextTabId
methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal &&
(it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.imageWithTextTabId
} == true
}
)

View File

@ -65,14 +65,14 @@ class CreateButtonRemoverBytecodePatch : BytecodePatch(
} ?: return PivotBarCreateButtonViewFingerprint.toErrorResult()
}
internal companion object {
private companion object {
const val hook =
"invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, $GENERAL_LAYOUT" +
"->" +
"hideCreateButton(Landroid/view/View;)V"
private lateinit var createRef: DexBackedMethodReference
lateinit var createRef: DexBackedMethodReference
private var isSeondary: Boolean = false
var isSeondary: Boolean = false
}
}

View File

@ -3,19 +3,18 @@ package app.revanced.patches.youtube.layout.general.pivotbar.shortsbutton.byteco
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
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.patches.youtube.layout.general.pivotbar.shortsbutton.bytecode.fingerprints.PivotBarEnumFingerprint
import app.revanced.patches.youtube.layout.general.pivotbar.shortsbutton.bytecode.fingerprints.PivotBarShortsButtonViewFingerprint
import app.revanced.shared.annotation.YouTubeCompatibility
import app.revanced.shared.extensions.toErrorResult
import app.revanced.shared.fingerprints.PivotBarFingerprint
import app.revanced.shared.util.integrations.Constants.GENERAL_LAYOUT
import app.revanced.shared.util.pivotbar.InjectionUtils.injectHook
import app.revanced.shared.util.pivotbar.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.shared.util.pivotbar.InjectionUtils.injectHook
@Name("hide-shorts-button")
@YouTubeCompatibility
@ -29,42 +28,48 @@ class ShortsButtonRemoverBytecodePatch : BytecodePatch(
* Resolve fingerprints
*/
val pivotBarResult = PivotBarFingerprint.result ?: return PatchResultError("PivotBarFingerprint failed")
val fingerprintResults = arrayOf(PivotBarEnumFingerprint, PivotBarShortsButtonViewFingerprint)
.onEach {
val resolutionSucceeded = it.resolve(
context,
pivotBarResult.mutableMethod,
pivotBarResult.mutableClass
)
PivotBarFingerprint.result?.let { parentResult ->
with (
arrayOf(
PivotBarEnumFingerprint,
PivotBarShortsButtonViewFingerprint
).onEach {
it.resolve(
context,
parentResult.mutableMethod,
parentResult.mutableClass
)
}.map {
it.result?.scanResult?.patternScanResult ?: return it.toErrorResult()
}
) {
val enumScanResult = this[0]
val buttonViewResult = this[1]
if (!resolutionSucceeded) return PatchResultError("${it.name} failed")
val enumHookInsertIndex = enumScanResult.startIndex + 2
val buttonHookInsertIndex = buttonViewResult.endIndex
mapOf(
buttonHook to buttonHookInsertIndex,
enumHook to enumHookInsertIndex
).forEach { (hook, insertIndex) ->
parentResult.mutableMethod.injectHook(hook, insertIndex)
}
}
.map { it.result!!.scanResult.patternScanResult!! }
val enumScanResult = fingerprintResults[0]
val buttonViewResult = fingerprintResults[1]
val enumHookInsertIndex = enumScanResult.startIndex + 2
val buttonHookInsertIndex = buttonViewResult.endIndex
/*
* Inject hooks
*/
val enumHook =
"sput-object v$REGISTER_TEMPLATE_REPLACEMENT, $GENERAL_LAYOUT->lastPivotTab:Ljava/lang/Enum;"
val buttonHook =
"invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, $GENERAL_LAYOUT->hideShortsButton(Landroid/view/View;)V"
// Inject bottom to top to not mess up the indices
mapOf(
buttonHook to buttonHookInsertIndex,
enumHook to enumHookInsertIndex
).forEach { (hook, insertIndex) ->
pivotBarResult.mutableMethod.injectHook(hook, insertIndex)
}
} ?: return PivotBarFingerprint.toErrorResult()
return PatchResultSuccess()
}
private companion object {
const val enumHook =
"sput-object v$REGISTER_TEMPLATE_REPLACEMENT, $GENERAL_LAYOUT" +
"->" +
"lastPivotTab:Ljava/lang/Enum;"
const val buttonHook =
"invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, $GENERAL_LAYOUT" +
"->" +
"hideShortsButton(Landroid/view/View;)V"
}
}

View File

@ -30,12 +30,15 @@ class WideSearchbarBytecodePatch : BytecodePatch(
WideSearchbarOneParentFingerprint to WideSearchbarOneFingerprint,
WideSearchbarTwoParentFingerprint to WideSearchbarTwoFingerprint
).map { (parentFingerprint, fingerprint) ->
parentFingerprint.result?.let { parentResult ->
fingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let {
parentFingerprint.result?.classDef?.let { classDef ->
fingerprint.also { it.resolve(context, classDef) }.result?.let {
val index = if (fingerprint == WideSearchbarOneFingerprint) it.scanResult.patternScanResult!!.endIndex
else it.scanResult.patternScanResult!!.startIndex
val targetMethod =
context
.toMethodWalker(it.method)
.nextMethod(it.scanResult.patternScanResult!!.endIndex, true)
.nextMethod(index, true)
.getMethod() as MutableMethod
injectSearchBarHook(targetMethod)