Skip to content

Commit eed856d

Browse files
authored
fix(YouTube - Spoof client): Fix tracking history on brand accounts (#3480)
1 parent e8d4813 commit eed856d

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofClientPatch.kt

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ object SpoofClientPatch : BytecodePatch(
8383

8484
// Player speed menu item.
8585
CreatePlaybackSpeedMenuItemFingerprint,
86+
87+
// Watch history.
88+
GetTrackingUriFingerprint,
8689
),
8790
) {
8891
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
@@ -153,7 +156,7 @@ object SpoofClientPatch : BytecodePatch(
153156
.getInstructions().find { instruction ->
154157
// requestMessage.clientInfo = clientInfoBuilder.build();
155158
instruction.opcode == Opcode.IPUT_OBJECT &&
156-
instruction.getReference<FieldReference>()?.type == CLIENT_INFO_CLASS_DESCRIPTOR
159+
instruction.getReference<FieldReference>()?.type == CLIENT_INFO_CLASS_DESCRIPTOR
157160
}?.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoField")
158161

159162
// Client info object's client type field.
@@ -164,13 +167,15 @@ object SpoofClientPatch : BytecodePatch(
164167
// Client info object's client version field.
165168
val clientInfoClientVersionField = result.mutableMethod
166169
.getInstruction(result.scanResult.stringsScanResult!!.matches.first().index + 1)
167-
.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientVersionField")
170+
.getReference<FieldReference>()
171+
?: throw PatchException("Could not find clientInfoClientVersionField")
168172

169173
Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField)
170174
}
171175

172176
val clientInfoClientModelField = CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().let {
173-
val getClientModelIndex = CreatePlayerRequestBodyWithModelFingerprint.indexOfBuildModelInstruction(it.method)
177+
val getClientModelIndex =
178+
CreatePlayerRequestBodyWithModelFingerprint.indexOfBuildModelInstruction(it.method)
174179

175180
// The next IPUT_OBJECT instruction after getting the client model is setting the client model field.
176181
val index = it.mutableMethod.indexOfFirstInstructionOrThrow(getClientModelIndex) {
@@ -198,7 +203,7 @@ object SpoofClientPatch : BytecodePatch(
198203
addInstruction(
199204
checkCastIndex + 1,
200205
"invoke-static { v$requestMessageInstanceRegister }," +
201-
" ${result.classDef.type}->$setClientInfoMethodName($clientInfoContainerClassName)V",
206+
" ${result.classDef.type}->$setClientInfoMethodName($clientInfoContainerClassName)V",
202207
)
203208
}
204209

@@ -291,7 +296,8 @@ object SpoofClientPatch : BytecodePatch(
291296

292297
it.mutableMethod.apply {
293298
// Find the conditional check if the playback speed menu item is not created.
294-
val shouldCreateMenuIndex = indexOfFirstInstructionOrThrow(scanResult.endIndex) { opcode == Opcode.IF_EQZ }
299+
val shouldCreateMenuIndex =
300+
indexOfFirstInstructionOrThrow(scanResult.endIndex) { opcode == Opcode.IF_EQZ }
295301
val shouldCreateMenuRegister = getInstruction<OneRegisterInstruction>(shouldCreateMenuIndex).registerA
296302

297303
addInstructions(
@@ -305,5 +311,24 @@ object SpoofClientPatch : BytecodePatch(
305311
}
306312

307313
// endregion
314+
315+
// Fix watch history if spoofing to iOS.
316+
317+
GetTrackingUriFingerprint.resultOrThrow().let {
318+
it.mutableMethod.apply {
319+
val returnUrlIndex = it.scanResult.patternScanResult!!.endIndex
320+
val urlRegister = getInstruction<OneRegisterInstruction>(returnUrlIndex).registerA
321+
322+
addInstructions(
323+
returnUrlIndex,
324+
"""
325+
invoke-static { v$urlRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideTrackingUrl(Landroid/net/Uri;)Landroid/net/Uri;
326+
move-result-object v$urlRegister
327+
"""
328+
)
329+
}
330+
}
331+
332+
// endregion
308333
}
309334
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
2+
3+
import app.revanced.patcher.extensions.or
4+
import app.revanced.patcher.fingerprint.MethodFingerprint
5+
import com.android.tools.smali.dexlib2.AccessFlags
6+
import com.android.tools.smali.dexlib2.Opcode
7+
8+
internal object GetTrackingUriFingerprint : MethodFingerprint(
9+
returnType = "Landroid/net/Uri;",
10+
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
11+
parameters = emptyList(),
12+
opcodes = listOf(
13+
Opcode.IGET_OBJECT,
14+
Opcode.INVOKE_STATIC,
15+
Opcode.MOVE_RESULT_OBJECT,
16+
Opcode.RETURN_OBJECT
17+
),
18+
customFingerprint = { _, classDef ->
19+
classDef.endsWith("TrackingUrlModel;")
20+
}
21+
)

src/main/resources/addresources/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
11321132
<string name="revanced_spoof_client_summary_off">Client is not spoofed\n\nVideo playback may not work</string>
11331133
<string name="revanced_spoof_client_user_dialog_message">Turning off this setting may cause video playback issues.</string>
11341134
<string name="revanced_spoof_client_use_ios_title">Spoof client to iOS</string>
1135-
<string name="revanced_spoof_client_use_ios_summary_on">Client is currently spoofed to iOS\n\nSide effects include:\n• No HDR video\n• Watch history may not work\n• Higher video qualities may be missing\n• Live streams cannot play as audio only\n• Live streams not available on Android 8.0</string>
1135+
<string name="revanced_spoof_client_use_ios_summary_on">Client is currently spoofed to iOS\n\nSide effects include:\n• No HDR video\n• Higher video qualities may be missing\n• Live streams cannot play as audio only\n• Live streams not available on Android 8.0</string>
11361136
<string name="revanced_spoof_client_use_ios_summary_off">Client is currently spoofed to Android VR\n\nSide effects include:\n• No HDR video\n• Kids videos do not playback\n• Paused videos can randomly resume\n• Low quality Shorts seekbar thumbnails\n• Download action button is always hidden\n• End screen cards are always hidden</string>
11371137
<string name="revanced_spoof_client_storyboard_timeout">Spoof client thumbnails not available (API timed out)</string>
11381138
<string name="revanced_spoof_client_storyboard_io_exception">Spoof client thumbnails temporarily not available: %s</string>

0 commit comments

Comments
 (0)