mirror of
https://github.com/revanced/revanced-patches
synced 2025-01-06 00:06:00 +01:00
feat(YouTube): Add Bypass image region restrictions
patch (#3442)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
parent
d37184d6bd
commit
765fab2af2
@ -1724,6 +1724,12 @@ public final class app/revanced/patches/youtube/layout/thumbnails/AlternativeThu
|
|||||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/youtube/layout/thumbnails/BypassImageRegionRestrictions : app/revanced/patcher/patch/BytecodePatch {
|
||||||
|
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/thumbnails/BypassImageRegionRestrictions;
|
||||||
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch : app/revanced/patcher/patch/BytecodePatch {
|
public final class app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/announcements/AnnouncementsPatch;
|
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/announcements/AnnouncementsPatch;
|
||||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
@ -1790,6 +1796,16 @@ public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourceP
|
|||||||
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook : app/revanced/patcher/patch/BytecodePatch {
|
||||||
|
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook;
|
||||||
|
public final fun addImageUrlErrorCallbackHook (Ljava/lang/String;)V
|
||||||
|
public final fun addImageUrlHook (Ljava/lang/String;Z)V
|
||||||
|
public static synthetic fun addImageUrlHook$default (Lapp/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook;Ljava/lang/String;ZILjava/lang/Object;)V
|
||||||
|
public final fun addImageUrlSuccessCallbackHook (Ljava/lang/String;)V
|
||||||
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/youtube/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
|
public final class app/revanced/patches/youtube/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
|
||||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/integrations/IntegrationsPatch;
|
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/integrations/IntegrationsPatch;
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,18 @@
|
|||||||
package app.revanced.patches.youtube.layout.thumbnails
|
package app.revanced.patches.youtube.layout.thumbnails
|
||||||
|
|
||||||
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.addInstructions
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
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.proxy.mutableTypes.MutableMethod
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
|
||||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||||
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
|
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.MessageDigestImageUrlFingerprint
|
import app.revanced.patches.youtube.misc.imageurlhook.CronetImageUrlHook
|
||||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.MessageDigestImageUrlParentFingerprint
|
|
||||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.RequestFingerprint
|
|
||||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnFailureFingerprint
|
|
||||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
|
|
||||||
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.navigation.NavigationBarHookPatch
|
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||||
import app.revanced.util.resultOrThrow
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Alternative thumbnails",
|
name = "Alternative thumbnails",
|
||||||
@ -39,7 +21,8 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
|||||||
IntegrationsPatch::class,
|
IntegrationsPatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
AddResourcesPatch::class,
|
AddResourcesPatch::class,
|
||||||
NavigationBarHookPatch::class
|
NavigationBarHookPatch::class,
|
||||||
|
CronetImageUrlHook::class
|
||||||
],
|
],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage(
|
CompatiblePackage(
|
||||||
@ -74,65 +57,10 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object AlternativeThumbnailsPatch : BytecodePatch(
|
object AlternativeThumbnailsPatch : BytecodePatch(emptySet()) {
|
||||||
setOf(
|
|
||||||
MessageDigestImageUrlParentFingerprint,
|
|
||||||
OnResponseStartedFingerprint,
|
|
||||||
RequestFingerprint,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||||
"Lapp/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch;"
|
"Lapp/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch;"
|
||||||
|
|
||||||
private lateinit var loadImageUrlMethod: MutableMethod
|
|
||||||
private var loadImageUrlIndex = 0
|
|
||||||
|
|
||||||
private lateinit var loadImageSuccessCallbackMethod: MutableMethod
|
|
||||||
private var loadImageSuccessCallbackIndex = 0
|
|
||||||
|
|
||||||
private lateinit var loadImageErrorCallbackMethod: MutableMethod
|
|
||||||
private var loadImageErrorCallbackIndex = 0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param highPriority If the hook should be called before all other hooks.
|
|
||||||
*/
|
|
||||||
@Suppress("SameParameterValue")
|
|
||||||
private fun addImageUrlHook(targetMethodClass: String, highPriority: Boolean) {
|
|
||||||
loadImageUrlMethod.addInstructions(
|
|
||||||
if (highPriority) 0 else loadImageUrlIndex,
|
|
||||||
"""
|
|
||||||
invoke-static { p1 }, $targetMethodClass->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object p1
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
loadImageUrlIndex += 2
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a connection completed, which includes normal 200 responses but also includes
|
|
||||||
* status 404 and other error like http responses.
|
|
||||||
*/
|
|
||||||
@Suppress("SameParameterValue")
|
|
||||||
private fun addImageUrlSuccessCallbackHook(targetMethodClass: String) {
|
|
||||||
loadImageSuccessCallbackMethod.addInstruction(
|
|
||||||
loadImageSuccessCallbackIndex++,
|
|
||||||
"invoke-static { p1, p2 }, $targetMethodClass->handleCronetSuccess(" +
|
|
||||||
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;)V",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a connection outright failed to complete any connection.
|
|
||||||
*/
|
|
||||||
@Suppress("SameParameterValue")
|
|
||||||
private fun addImageUrlErrorCallbackHook(targetMethodClass: String) {
|
|
||||||
loadImageErrorCallbackMethod.addInstruction(
|
|
||||||
loadImageErrorCallbackIndex++,
|
|
||||||
"invoke-static { p1, p2, p3 }, $targetMethodClass->handleCronetFailure(" +
|
|
||||||
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;Ljava/io/IOException;)V",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
AddResourcesPatch(this::class)
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
@ -177,62 +105,8 @@ object AlternativeThumbnailsPatch : BytecodePatch(
|
|||||||
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null)
|
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
|
CronetImageUrlHook.addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||||
also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
|
CronetImageUrlHook.addImageUrlSuccessCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||||
|
CronetImageUrlHook.addImageUrlErrorCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||||
fun MethodFingerprint.resolveAndLetMutableMethod(
|
|
||||||
fingerprint: MethodFingerprint,
|
|
||||||
block: (MutableMethod) -> Unit,
|
|
||||||
) = alsoResolve(fingerprint).also { block(it.mutableMethod) }
|
|
||||||
|
|
||||||
MessageDigestImageUrlFingerprint.resolveAndLetMutableMethod(MessageDigestImageUrlParentFingerprint) {
|
|
||||||
loadImageUrlMethod = it
|
|
||||||
addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
OnSucceededFingerprint.resolveAndLetMutableMethod(OnResponseStartedFingerprint) {
|
|
||||||
loadImageSuccessCallbackMethod = it
|
|
||||||
addImageUrlSuccessCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
|
||||||
}
|
|
||||||
|
|
||||||
OnFailureFingerprint.resolveAndLetMutableMethod(OnResponseStartedFingerprint) {
|
|
||||||
loadImageErrorCallbackMethod = it
|
|
||||||
addImageUrlErrorCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
RequestFingerprint.resultOrThrow().apply {
|
|
||||||
// The url is the only string field that is set inside the constructor.
|
|
||||||
val urlFieldInstruction = mutableMethod.getInstructions().first {
|
|
||||||
if (it.opcode != Opcode.IPUT_OBJECT) return@first false
|
|
||||||
|
|
||||||
val reference = (it as ReferenceInstruction).reference as FieldReference
|
|
||||||
reference.type == "Ljava/lang/String;"
|
|
||||||
} as ReferenceInstruction
|
|
||||||
|
|
||||||
val urlFieldName = (urlFieldInstruction.reference as FieldReference).name
|
|
||||||
val definingClass = RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
|
||||||
val addedMethodName = "getHookedUrl"
|
|
||||||
mutableClass.methods.add(
|
|
||||||
ImmutableMethod(
|
|
||||||
definingClass,
|
|
||||||
addedMethodName,
|
|
||||||
emptyList(),
|
|
||||||
"Ljava/lang/String;",
|
|
||||||
AccessFlags.PUBLIC.value,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
MutableMethodImplementation(2),
|
|
||||||
).toMutable().apply {
|
|
||||||
addInstructions(
|
|
||||||
"""
|
|
||||||
iget-object v0, p0, $definingClass->$urlFieldName:Ljava/lang/String;
|
|
||||||
return-object v0
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.thumbnails
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||||
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
|
import app.revanced.patches.youtube.misc.imageurlhook.CronetImageUrlHook
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||||
|
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||||
|
|
||||||
|
@Patch(
|
||||||
|
name = "Bypass image region restrictions",
|
||||||
|
description = "Adds an option to use a different host for user avatar and channel images," +
|
||||||
|
"and can fix missing images that are blocked in some countries.",
|
||||||
|
dependencies = [
|
||||||
|
IntegrationsPatch::class,
|
||||||
|
SettingsPatch::class,
|
||||||
|
AddResourcesPatch::class,
|
||||||
|
CronetImageUrlHook::class
|
||||||
|
],
|
||||||
|
compatiblePackages = [
|
||||||
|
CompatiblePackage(
|
||||||
|
"com.google.android.youtube",
|
||||||
|
[
|
||||||
|
"18.32.39",
|
||||||
|
"18.37.36",
|
||||||
|
"18.38.44",
|
||||||
|
"18.43.45",
|
||||||
|
"18.44.41",
|
||||||
|
"18.45.43",
|
||||||
|
"18.48.39",
|
||||||
|
"18.49.37",
|
||||||
|
"19.01.34",
|
||||||
|
"19.02.39",
|
||||||
|
"19.03.36",
|
||||||
|
"19.04.38",
|
||||||
|
"19.05.36",
|
||||||
|
"19.06.39",
|
||||||
|
"19.07.40",
|
||||||
|
"19.08.36",
|
||||||
|
"19.09.38",
|
||||||
|
"19.10.39",
|
||||||
|
"19.11.43",
|
||||||
|
"19.12.41",
|
||||||
|
"19.13.37",
|
||||||
|
"19.14.43",
|
||||||
|
"19.15.36",
|
||||||
|
"19.16.39",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
@Suppress("unused")
|
||||||
|
object BypassImageRegionRestrictions : BytecodePatch(emptySet()) {
|
||||||
|
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||||
|
"Lapp/revanced/integrations/youtube/patches/BypassImageRegionRestrictionsPatch;"
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext) {
|
||||||
|
AddResourcesPatch(this::class)
|
||||||
|
|
||||||
|
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||||
|
SwitchPreference("revanced_bypass_image_region_restrictions")
|
||||||
|
)
|
||||||
|
|
||||||
|
// A priority hook is not needed, as the image urls of interest are not modified
|
||||||
|
// by AlternativeThumbnails or any other patch in this repo.
|
||||||
|
CronetImageUrlHook.addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.imageurlhook
|
||||||
|
|
||||||
|
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.getInstructions
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
|
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.MessageDigestImageUrlFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.MessageDigestImageUrlParentFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.RequestFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnFailureFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnSucceededFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||||
|
import app.revanced.util.resultOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||||
|
|
||||||
|
@Patch(
|
||||||
|
description = "Hooks Cronet image urls",
|
||||||
|
dependencies = [
|
||||||
|
IntegrationsPatch::class
|
||||||
|
]
|
||||||
|
)
|
||||||
|
object CronetImageUrlHook : BytecodePatch(
|
||||||
|
setOf(
|
||||||
|
MessageDigestImageUrlParentFingerprint,
|
||||||
|
OnResponseStartedFingerprint,
|
||||||
|
RequestFingerprint
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
private lateinit var loadImageUrlMethod: MutableMethod
|
||||||
|
private var loadImageUrlIndex = 0
|
||||||
|
|
||||||
|
private lateinit var loadImageSuccessCallbackMethod: MutableMethod
|
||||||
|
private var loadImageSuccessCallbackIndex = 0
|
||||||
|
|
||||||
|
private lateinit var loadImageErrorCallbackMethod: MutableMethod
|
||||||
|
private var loadImageErrorCallbackIndex = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param highPriority If the hook should be called before all other hooks.
|
||||||
|
*/
|
||||||
|
fun addImageUrlHook(targetMethodClass: String, highPriority: Boolean = false) {
|
||||||
|
loadImageUrlMethod.addInstructions(
|
||||||
|
if (highPriority) 0 else loadImageUrlIndex,
|
||||||
|
"""
|
||||||
|
invoke-static { p1 }, $targetMethodClass->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
move-result-object p1
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
loadImageUrlIndex += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a connection completed, which includes normal 200 responses but also includes
|
||||||
|
* status 404 and other error like http responses.
|
||||||
|
*/
|
||||||
|
fun addImageUrlSuccessCallbackHook(targetMethodClass: String) {
|
||||||
|
loadImageSuccessCallbackMethod.addInstruction(
|
||||||
|
loadImageSuccessCallbackIndex++,
|
||||||
|
"invoke-static { p1, p2 }, $targetMethodClass->handleCronetSuccess(" +
|
||||||
|
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;)V",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a connection outright failed to complete any connection.
|
||||||
|
*/
|
||||||
|
fun addImageUrlErrorCallbackHook(targetMethodClass: String) {
|
||||||
|
loadImageErrorCallbackMethod.addInstruction(
|
||||||
|
loadImageErrorCallbackIndex++,
|
||||||
|
"invoke-static { p1, p2, p3 }, $targetMethodClass->handleCronetFailure(" +
|
||||||
|
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;Ljava/io/IOException;)V",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext) {
|
||||||
|
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
|
||||||
|
also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
|
||||||
|
|
||||||
|
loadImageUrlMethod = MessageDigestImageUrlFingerprint
|
||||||
|
.alsoResolve(MessageDigestImageUrlParentFingerprint).mutableMethod
|
||||||
|
|
||||||
|
loadImageSuccessCallbackMethod = OnSucceededFingerprint
|
||||||
|
.alsoResolve(OnResponseStartedFingerprint).mutableMethod
|
||||||
|
|
||||||
|
loadImageErrorCallbackMethod = OnFailureFingerprint
|
||||||
|
.alsoResolve(OnResponseStartedFingerprint).mutableMethod
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
RequestFingerprint.resultOrThrow().apply {
|
||||||
|
// The url is the only string field that is set inside the constructor.
|
||||||
|
val urlFieldInstruction = mutableMethod.getInstructions().single {
|
||||||
|
if (it.opcode != Opcode.IPUT_OBJECT) return@single false
|
||||||
|
|
||||||
|
val reference = (it as ReferenceInstruction).reference as FieldReference
|
||||||
|
reference.type == "Ljava/lang/String;"
|
||||||
|
} as ReferenceInstruction
|
||||||
|
|
||||||
|
val urlFieldName = (urlFieldInstruction.reference as FieldReference).name
|
||||||
|
val definingClass = RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
||||||
|
val addedMethodName = "getHookedUrl"
|
||||||
|
mutableClass.methods.add(
|
||||||
|
ImmutableMethod(
|
||||||
|
definingClass,
|
||||||
|
addedMethodName,
|
||||||
|
emptyList(),
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
AccessFlags.PUBLIC.value,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
MutableMethodImplementation(2),
|
||||||
|
).toMutable().apply {
|
||||||
|
addInstructions(
|
||||||
|
"""
|
||||||
|
iget-object v0, p0, $definingClass->$urlFieldName:Ljava/lang/String;
|
||||||
|
return-object v0
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints
|
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints
|
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,8 +1,8 @@
|
|||||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet
|
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
internal object RequestFingerprint : MethodFingerprint(
|
internal object RequestFingerprint : MethodFingerprint(
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback
|
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback
|
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback
|
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -998,6 +998,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
|||||||
<string name="revanced_seekbar_custom_color_value_summary">The color of the seekbar</string>
|
<string name="revanced_seekbar_custom_color_value_summary">The color of the seekbar</string>
|
||||||
<string name="revanced_seekbar_custom_color_invalid">Invalid seekbar color value. Using default value.</string>
|
<string name="revanced_seekbar_custom_color_invalid">Invalid seekbar color value. Using default value.</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||||
|
<string name="revanced_bypass_image_region_restrictions_title">Bypass image region restrictions</string>
|
||||||
|
<string name="revanced_bypass_image_region_restrictions_summary_on">Using image host yt4.ggpht.com</string>
|
||||||
|
<string name="revanced_bypass_image_region_restrictions_summary_off">Using original image host\n\nEnabling this can fix missing images that are blocked in some regions</string>
|
||||||
|
</patch>
|
||||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||||
<string name="revanced_alt_thumbnail_home_title">Home tab</string>
|
<string name="revanced_alt_thumbnail_home_title">Home tab</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user