Skip to content

Commit 9ef51ab

Browse files
LisoUseInAIKyriosoSumAtrIX
andauthored
feat(YouTube): Add Bypass image region restrictions patch (#3442)
Co-authored-by: oSumAtrIX <[email protected]>
1 parent 1d31565 commit 9ef51ab

File tree

11 files changed

+240
-140
lines changed

11 files changed

+240
-140
lines changed

api/revanced-patches.api

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,12 @@ public final class app/revanced/patches/youtube/layout/thumbnails/AlternativeThu
17241724
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
17251725
}
17261726

1727+
public final class app/revanced/patches/youtube/layout/thumbnails/BypassImageRegionRestrictions : app/revanced/patcher/patch/BytecodePatch {
1728+
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/thumbnails/BypassImageRegionRestrictions;
1729+
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
1730+
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
1731+
}
1732+
17271733
public final class app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch : app/revanced/patcher/patch/BytecodePatch {
17281734
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/announcements/AnnouncementsPatch;
17291735
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1790,6 +1796,16 @@ public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourceP
17901796
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
17911797
}
17921798

1799+
public final class app/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook : app/revanced/patcher/patch/BytecodePatch {
1800+
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook;
1801+
public final fun addImageUrlErrorCallbackHook (Ljava/lang/String;)V
1802+
public final fun addImageUrlHook (Ljava/lang/String;Z)V
1803+
public static synthetic fun addImageUrlHook$default (Lapp/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook;Ljava/lang/String;ZILjava/lang/Object;)V
1804+
public final fun addImageUrlSuccessCallbackHook (Ljava/lang/String;)V
1805+
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
1806+
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
1807+
}
1808+
17931809
public final class app/revanced/patches/youtube/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
17941810
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/integrations/IntegrationsPatch;
17951811
}
Lines changed: 7 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,18 @@
11
package app.revanced.patches.youtube.layout.thumbnails
22

33
import app.revanced.patcher.data.BytecodeContext
4-
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
5-
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
6-
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
7-
import app.revanced.patcher.fingerprint.MethodFingerprint
84
import app.revanced.patcher.patch.BytecodePatch
95
import app.revanced.patcher.patch.annotation.CompatiblePackage
106
import app.revanced.patcher.patch.annotation.Patch
11-
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
12-
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
137
import app.revanced.patches.all.misc.resources.AddResourcesPatch
148
import app.revanced.patches.shared.misc.settings.preference.ListPreference
159
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
1610
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
1711
import app.revanced.patches.shared.misc.settings.preference.TextPreference
18-
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.MessageDigestImageUrlFingerprint
19-
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.MessageDigestImageUrlParentFingerprint
20-
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.RequestFingerprint
21-
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnFailureFingerprint
22-
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
23-
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint
12+
import app.revanced.patches.youtube.misc.imageurlhook.CronetImageUrlHook
2413
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
2514
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
2615
import app.revanced.patches.youtube.misc.settings.SettingsPatch
27-
import app.revanced.util.resultOrThrow
28-
import com.android.tools.smali.dexlib2.AccessFlags
29-
import com.android.tools.smali.dexlib2.Opcode
30-
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
31-
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
32-
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
33-
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
3416

3517
@Patch(
3618
name = "Alternative thumbnails",
@@ -39,7 +21,8 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
3921
IntegrationsPatch::class,
4022
SettingsPatch::class,
4123
AddResourcesPatch::class,
42-
NavigationBarHookPatch::class
24+
NavigationBarHookPatch::class,
25+
CronetImageUrlHook::class
4326
],
4427
compatiblePackages = [
4528
CompatiblePackage(
@@ -74,65 +57,10 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
7457
],
7558
)
7659
@Suppress("unused")
77-
object AlternativeThumbnailsPatch : BytecodePatch(
78-
setOf(
79-
MessageDigestImageUrlParentFingerprint,
80-
OnResponseStartedFingerprint,
81-
RequestFingerprint,
82-
),
83-
) {
60+
object AlternativeThumbnailsPatch : BytecodePatch(emptySet()) {
8461
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
8562
"Lapp/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch;"
8663

87-
private lateinit var loadImageUrlMethod: MutableMethod
88-
private var loadImageUrlIndex = 0
89-
90-
private lateinit var loadImageSuccessCallbackMethod: MutableMethod
91-
private var loadImageSuccessCallbackIndex = 0
92-
93-
private lateinit var loadImageErrorCallbackMethod: MutableMethod
94-
private var loadImageErrorCallbackIndex = 0
95-
96-
/**
97-
* @param highPriority If the hook should be called before all other hooks.
98-
*/
99-
@Suppress("SameParameterValue")
100-
private fun addImageUrlHook(targetMethodClass: String, highPriority: Boolean) {
101-
loadImageUrlMethod.addInstructions(
102-
if (highPriority) 0 else loadImageUrlIndex,
103-
"""
104-
invoke-static { p1 }, $targetMethodClass->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
105-
move-result-object p1
106-
""",
107-
)
108-
loadImageUrlIndex += 2
109-
}
110-
111-
/**
112-
* If a connection completed, which includes normal 200 responses but also includes
113-
* status 404 and other error like http responses.
114-
*/
115-
@Suppress("SameParameterValue")
116-
private fun addImageUrlSuccessCallbackHook(targetMethodClass: String) {
117-
loadImageSuccessCallbackMethod.addInstruction(
118-
loadImageSuccessCallbackIndex++,
119-
"invoke-static { p1, p2 }, $targetMethodClass->handleCronetSuccess(" +
120-
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;)V",
121-
)
122-
}
123-
124-
/**
125-
* If a connection outright failed to complete any connection.
126-
*/
127-
@Suppress("SameParameterValue")
128-
private fun addImageUrlErrorCallbackHook(targetMethodClass: String) {
129-
loadImageErrorCallbackMethod.addInstruction(
130-
loadImageErrorCallbackIndex++,
131-
"invoke-static { p1, p2, p3 }, $targetMethodClass->handleCronetFailure(" +
132-
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;Ljava/io/IOException;)V",
133-
)
134-
}
135-
13664
override fun execute(context: BytecodeContext) {
13765
AddResourcesPatch(this::class)
13866

@@ -177,62 +105,8 @@ object AlternativeThumbnailsPatch : BytecodePatch(
177105
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null)
178106
)
179107

180-
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
181-
also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
182-
183-
fun MethodFingerprint.resolveAndLetMutableMethod(
184-
fingerprint: MethodFingerprint,
185-
block: (MutableMethod) -> Unit,
186-
) = alsoResolve(fingerprint).also { block(it.mutableMethod) }
187-
188-
MessageDigestImageUrlFingerprint.resolveAndLetMutableMethod(MessageDigestImageUrlParentFingerprint) {
189-
loadImageUrlMethod = it
190-
addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR, true)
191-
}
192-
193-
OnSucceededFingerprint.resolveAndLetMutableMethod(OnResponseStartedFingerprint) {
194-
loadImageSuccessCallbackMethod = it
195-
addImageUrlSuccessCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
196-
}
197-
198-
OnFailureFingerprint.resolveAndLetMutableMethod(OnResponseStartedFingerprint) {
199-
loadImageErrorCallbackMethod = it
200-
addImageUrlErrorCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
201-
}
202-
203-
// The URL is required for the failure callback hook, but the URL field is obfuscated.
204-
// Add a helper get method that returns the URL field.
205-
RequestFingerprint.resultOrThrow().apply {
206-
// The url is the only string field that is set inside the constructor.
207-
val urlFieldInstruction = mutableMethod.getInstructions().first {
208-
if (it.opcode != Opcode.IPUT_OBJECT) return@first false
209-
210-
val reference = (it as ReferenceInstruction).reference as FieldReference
211-
reference.type == "Ljava/lang/String;"
212-
} as ReferenceInstruction
213-
214-
val urlFieldName = (urlFieldInstruction.reference as FieldReference).name
215-
val definingClass = RequestFingerprint.IMPLEMENTATION_CLASS_NAME
216-
val addedMethodName = "getHookedUrl"
217-
mutableClass.methods.add(
218-
ImmutableMethod(
219-
definingClass,
220-
addedMethodName,
221-
emptyList(),
222-
"Ljava/lang/String;",
223-
AccessFlags.PUBLIC.value,
224-
null,
225-
null,
226-
MutableMethodImplementation(2),
227-
).toMutable().apply {
228-
addInstructions(
229-
"""
230-
iget-object v0, p0, $definingClass->$urlFieldName:Ljava/lang/String;
231-
return-object v0
232-
""",
233-
)
234-
},
235-
)
236-
}
108+
CronetImageUrlHook.addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR)
109+
CronetImageUrlHook.addImageUrlSuccessCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
110+
CronetImageUrlHook.addImageUrlErrorCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
237111
}
238112
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package app.revanced.patches.youtube.layout.thumbnails
2+
3+
import app.revanced.patcher.data.BytecodeContext
4+
import app.revanced.patcher.patch.BytecodePatch
5+
import app.revanced.patcher.patch.annotation.CompatiblePackage
6+
import app.revanced.patcher.patch.annotation.Patch
7+
import app.revanced.patches.all.misc.resources.AddResourcesPatch
8+
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
9+
import app.revanced.patches.youtube.misc.imageurlhook.CronetImageUrlHook
10+
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
11+
import app.revanced.patches.youtube.misc.settings.SettingsPatch
12+
13+
@Patch(
14+
name = "Bypass image region restrictions",
15+
description = "Adds an option to use a different host for user avatar and channel images," +
16+
"and can fix missing images that are blocked in some countries.",
17+
dependencies = [
18+
IntegrationsPatch::class,
19+
SettingsPatch::class,
20+
AddResourcesPatch::class,
21+
CronetImageUrlHook::class
22+
],
23+
compatiblePackages = [
24+
CompatiblePackage(
25+
"com.google.android.youtube",
26+
[
27+
"18.32.39",
28+
"18.37.36",
29+
"18.38.44",
30+
"18.43.45",
31+
"18.44.41",
32+
"18.45.43",
33+
"18.48.39",
34+
"18.49.37",
35+
"19.01.34",
36+
"19.02.39",
37+
"19.03.36",
38+
"19.04.38",
39+
"19.05.36",
40+
"19.06.39",
41+
"19.07.40",
42+
"19.08.36",
43+
"19.09.38",
44+
"19.10.39",
45+
"19.11.43",
46+
"19.12.41",
47+
"19.13.37",
48+
"19.14.43",
49+
"19.15.36",
50+
"19.16.39",
51+
]
52+
)
53+
]
54+
)
55+
@Suppress("unused")
56+
object BypassImageRegionRestrictions : BytecodePatch(emptySet()) {
57+
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
58+
"Lapp/revanced/integrations/youtube/patches/BypassImageRegionRestrictionsPatch;"
59+
60+
override fun execute(context: BytecodeContext) {
61+
AddResourcesPatch(this::class)
62+
63+
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
64+
SwitchPreference("revanced_bypass_image_region_restrictions")
65+
)
66+
67+
// A priority hook is not needed, as the image urls of interest are not modified
68+
// by AlternativeThumbnails or any other patch in this repo.
69+
CronetImageUrlHook.addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR)
70+
}
71+
}

0 commit comments

Comments
 (0)