diff --git a/extensions/shared/src/main/java/app/revanced/extension/music/settings/Settings.java b/extensions/shared/src/main/java/app/revanced/extension/music/settings/Settings.java index 41db5e573..72b0337ae 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/music/settings/Settings.java +++ b/extensions/shared/src/main/java/app/revanced/extension/music/settings/Settings.java @@ -263,15 +263,16 @@ public class Settings extends BaseSettings { ENABLE_CUSTOM_NAVIGATION_BAR_COLOR_VALUE.key, EXTERNAL_DOWNLOADER_PACKAGE_NAME.key, HIDE_ACCOUNT_MENU_FILTER_STRINGS.key, + OPEN_DEFAULT_APP_SETTINGS, + OPTIONAL_SPONSOR_BLOCK_SETTINGS_PREFIX, + RETURN_YOUTUBE_USERNAME_ABOUT.key, + RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT.key, + RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY.key, SB_API_URL.key, SETTINGS_IMPORT_EXPORT.key, SPOOF_APP_VERSION_TARGET.key, SPOOF_CLIENT_TYPE.key, - RETURN_YOUTUBE_USERNAME_ABOUT.key, - RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT.key, - RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY.key, - OPEN_DEFAULT_APP_SETTINGS, - OPTIONAL_SPONSOR_BLOCK_SETTINGS_PREFIX + WATCH_HISTORY_TYPE.key, }; /** diff --git a/extensions/shared/src/main/java/app/revanced/extension/music/settings/preference/ReVancedPreferenceFragment.java b/extensions/shared/src/main/java/app/revanced/extension/music/settings/preference/ReVancedPreferenceFragment.java index 6175d3d1f..bc949490c 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/music/settings/preference/ReVancedPreferenceFragment.java +++ b/extensions/shared/src/main/java/app/revanced/extension/music/settings/preference/ReVancedPreferenceFragment.java @@ -15,6 +15,7 @@ import static app.revanced.extension.music.settings.Settings.SB_API_URL; import static app.revanced.extension.music.settings.Settings.SETTINGS_IMPORT_EXPORT; import static app.revanced.extension.music.settings.Settings.SPOOF_APP_VERSION_TARGET; import static app.revanced.extension.music.settings.Settings.SPOOF_CLIENT_TYPE; +import static app.revanced.extension.music.settings.Settings.WATCH_HISTORY_TYPE; import static app.revanced.extension.music.utils.ExtendedUtils.getDialogBuilder; import static app.revanced.extension.music.utils.ExtendedUtils.getLayoutParams; import static app.revanced.extension.music.utils.RestartUtils.showRestartDialog; @@ -164,6 +165,7 @@ public class ReVancedPreferenceFragment extends PreferenceFragment { || settings.equals(DISABLE_MUSIC_VIDEO_IN_ALBUM_REDIRECT_TYPE) || settings.equals(RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT) || settings.equals(SPOOF_CLIENT_TYPE) + || settings.equals(WATCH_HISTORY_TYPE) ) { ResettableListPreference.showDialog(mActivity, enumSetting, 0); } diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/misc/WatchHistoryPatch.java b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/WatchHistoryPatch.java similarity index 83% rename from extensions/shared/src/main/java/app/revanced/extension/youtube/patches/misc/WatchHistoryPatch.java rename to extensions/shared/src/main/java/app/revanced/extension/shared/patches/WatchHistoryPatch.java index 01a002be4..46e3d1cf9 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/misc/WatchHistoryPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/WatchHistoryPatch.java @@ -1,9 +1,9 @@ -package app.revanced.extension.youtube.patches.misc; +package app.revanced.extension.shared.patches; import android.net.Uri; import app.revanced.extension.shared.utils.Logger; -import app.revanced.extension.youtube.settings.Settings; +import app.revanced.extension.shared.settings.BaseSettings; @SuppressWarnings("unused") public final class WatchHistoryPatch { @@ -18,7 +18,7 @@ public final class WatchHistoryPatch { private static final String WWW_TRACKING_URL_AUTHORITY = "www.youtube.com"; public static Uri replaceTrackingUrl(Uri trackingUrl) { - final WatchHistoryType watchHistoryType = Settings.WATCH_HISTORY_TYPE.get(); + final WatchHistoryType watchHistoryType = BaseSettings.WATCH_HISTORY_TYPE.get(); if (watchHistoryType != WatchHistoryType.ORIGINAL) { try { if (watchHistoryType == WatchHistoryType.REPLACE) { diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java b/extensions/shared/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java index a8c3e5fbd..f3a483ffd 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java @@ -5,6 +5,7 @@ import static java.lang.Boolean.TRUE; import static app.revanced.extension.shared.patches.PatchStatus.HideFullscreenAdsDefaultBoolean; import app.revanced.extension.shared.patches.ReturnYouTubeUsernamePatch.DisplayFormat; +import app.revanced.extension.shared.patches.WatchHistoryPatch.WatchHistoryType; import app.revanced.extension.shared.patches.client.MusicAppClient; import app.revanced.extension.shared.patches.client.YouTubeAppClient; import app.revanced.extension.shared.patches.spoof.SpoofStreamingDataPatch.AudioStreamLanguageOverrideAvailability; @@ -58,6 +59,8 @@ public class BaseSettings { public static final BooleanSetting DISABLE_QUIC_PROTOCOL = new BooleanSetting("revanced_disable_quic_protocol", FALSE, true); public static final BooleanSetting BYPASS_IMAGE_REGION_RESTRICTIONS = new BooleanSetting("revanced_bypass_image_region_restrictions", FALSE, true); + public static final EnumSetting WATCH_HISTORY_TYPE = new EnumSetting<>("revanced_watch_history_type", WatchHistoryType.REPLACE); + public static final BooleanSetting RETURN_YOUTUBE_USERNAME_ENABLED = new BooleanSetting("revanced_return_youtube_username_enabled", FALSE, true); public static final EnumSetting RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT = new EnumSetting<>("revanced_return_youtube_username_display_format", DisplayFormat.USERNAME_ONLY, true); public static final StringSetting RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY = new StringSetting("revanced_return_youtube_username_youtube_data_api_v3_developer_key", "", true, false); diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java index ee63c3946..e05f77cc1 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -37,7 +37,6 @@ import app.revanced.extension.youtube.patches.general.ChangeStartPagePatch.Start import app.revanced.extension.youtube.patches.general.LayoutSwitchPatch.FormFactor; import app.revanced.extension.youtube.patches.general.MiniplayerPatch; import app.revanced.extension.youtube.patches.general.YouTubeMusicActionsPatch; -import app.revanced.extension.youtube.patches.misc.WatchHistoryPatch.WatchHistoryType; import app.revanced.extension.youtube.patches.player.ExitFullscreenPatch.FullscreenMode; import app.revanced.extension.youtube.patches.shorts.AnimationFeedbackPatch.AnimationType; import app.revanced.extension.youtube.patches.shorts.ShortsRepeatStatePatch.ShortsLoopBehavior; @@ -591,7 +590,6 @@ public class Settings extends BaseSettings { public static final LongSetting DOUBLE_BACK_TO_CLOSE_TIMEOUT = new LongSetting("revanced_double_back_to_close_timeout", 2000L); // PreferenceScreen: Miscellaneous - Watch history - public static final EnumSetting WATCH_HISTORY_TYPE = new EnumSetting<>("revanced_watch_history_type", WatchHistoryType.REPLACE); // PreferenceScreen: Miscellaneous - Spoof streaming data diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/preference/WatchHistoryStatusPreference.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/preference/WatchHistoryStatusPreference.java index 104785fc1..c7f1e812a 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/preference/WatchHistoryStatusPreference.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/settings/preference/WatchHistoryStatusPreference.java @@ -8,9 +8,9 @@ import android.preference.Preference; import android.preference.PreferenceManager; import android.util.AttributeSet; +import app.revanced.extension.shared.patches.WatchHistoryPatch.WatchHistoryType; import app.revanced.extension.shared.settings.Setting; import app.revanced.extension.shared.utils.Utils; -import app.revanced.extension.youtube.patches.misc.WatchHistoryPatch.WatchHistoryType; import app.revanced.extension.youtube.settings.Settings; @SuppressWarnings({"deprecation", "unused"}) diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/watchhistory/WatchHistoryPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/watchhistory/WatchHistoryPatch.kt new file mode 100644 index 000000000..fdc321bca --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/watchhistory/WatchHistoryPatch.kt @@ -0,0 +1,33 @@ +package app.revanced.patches.music.misc.watchhistory + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.shared.trackingurlhook.hookWatchHistory +import app.revanced.patches.shared.trackingurlhook.trackingUrlHookPatch +import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE +import app.revanced.patches.music.utils.patch.PatchList.WATCH_HISTORY +import app.revanced.patches.music.utils.settings.CategoryType +import app.revanced.patches.music.utils.settings.addPreferenceWithIntent +import app.revanced.patches.music.utils.settings.settingsPatch + +@Suppress("unused") +val watchHistoryPatch = bytecodePatch( + WATCH_HISTORY.title, + WATCH_HISTORY.summary, +) { + compatibleWith(COMPATIBLE_PACKAGE) + + dependsOn( + settingsPatch, + trackingUrlHookPatch, + ) + + execute { + hookWatchHistory() + + addPreferenceWithIntent( + CategoryType.MISC, + "revanced_watch_history_type" + ) + } + +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/music/utils/patch/PatchList.kt b/patches/src/main/kotlin/app/revanced/patches/music/utils/patch/PatchList.kt index b4c7ed91c..02954da77 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/utils/patch/PatchList.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/utils/patch/PatchList.kt @@ -164,5 +164,9 @@ internal enum class PatchList( VISUAL_PREFERENCES_ICONS_FOR_YOUTUBE_MUSIC( "Visual preferences icons for YouTube Music", "Adds icons to specific preferences in the settings." + ), + WATCH_HISTORY( + "Watch history", + "Adds an option to change the domain of the watch history or check its status." ) } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/trackingurlhook/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/trackingurlhook/Fingerprints.kt new file mode 100644 index 000000000..eefb24db2 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/shared/trackingurlhook/Fingerprints.kt @@ -0,0 +1,35 @@ +package app.revanced.patches.shared.trackingurlhook + +import app.revanced.util.fingerprint.legacyFingerprint +import app.revanced.util.or +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal val trackingUrlModelFingerprint = legacyFingerprint( + name = "trackingUrlModelFingerprint", + returnType = "Landroid/net/Uri;", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = emptyList(), + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + ), +) + +/** + * On YouTube, this class is 'Lcom/google/android/libraries/youtube/innertube/model/player/TrackingUrlModel;' + * On YouTube Music, class names are obfuscated. + */ +internal val trackingUrlModelToStringFingerprint = legacyFingerprint( + name = "trackingUrlModelToStringFingerprint", + returnType = "Ljava/lang/String;", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = emptyList(), + strings = listOf( + "@", + "baseUrl->", + "params->", + "headers->", + ) +) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/trackingurlhook/TrackingUrlHookPatch.kt similarity index 69% rename from patches/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt rename to patches/src/main/kotlin/app/revanced/patches/shared/trackingurlhook/TrackingUrlHookPatch.kt index cd9761c7b..df2fe376d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/trackingurlhook/TrackingUrlHookPatch.kt @@ -1,9 +1,10 @@ -package app.revanced.patches.youtube.utils.trackingurlhook +package app.revanced.patches.shared.trackingurlhook import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.shared.extension.Constants.PATCHES_PATH import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow @@ -11,13 +12,21 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference +private const val EXTENSION_WATCH_HISTORY_CLASS_DESCRIPTOR = + "$PATCHES_PATH/WatchHistoryPatch;" + private lateinit var trackingUrlMethod: MutableMethod +/** + * This patch is currently used only for the 'Watch history' patch. + * In some versions, it can be used to forcibly generate 'Watch history'. + */ val trackingUrlHookPatch = bytecodePatch( description = "trackingUrlHookPatch" ) { execute { - trackingUrlMethod = trackingUrlModelFingerprint.methodOrThrow() + trackingUrlMethod = + trackingUrlModelFingerprint.methodOrThrow(trackingUrlModelToStringFingerprint) } } @@ -44,3 +53,6 @@ internal fun hookTrackingUrl( smaliInstruction ) } + +internal fun hookWatchHistory() = + hookTrackingUrl("$EXTENSION_WATCH_HISTORY_CLASS_DESCRIPTOR->replaceTrackingUrl(Landroid/net/Uri;)Landroid/net/Uri;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/watchhistory/WatchHistoryPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/watchhistory/WatchHistoryPatch.kt index 5916130c9..fb201c2ac 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/watchhistory/WatchHistoryPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/watchhistory/WatchHistoryPatch.kt @@ -1,13 +1,12 @@ package app.revanced.patches.youtube.misc.watchhistory import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.shared.trackingurlhook.hookWatchHistory +import app.revanced.patches.shared.trackingurlhook.trackingUrlHookPatch import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE -import app.revanced.patches.youtube.utils.extension.Constants.MISC_PATH import app.revanced.patches.youtube.utils.patch.PatchList.WATCH_HISTORY import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference import app.revanced.patches.youtube.utils.settings.settingsPatch -import app.revanced.patches.youtube.utils.trackingurlhook.hookTrackingUrl -import app.revanced.patches.youtube.utils.trackingurlhook.trackingUrlHookPatch @Suppress("unused") val watchHistoryPatch = bytecodePatch( @@ -23,7 +22,7 @@ val watchHistoryPatch = bytecodePatch( execute { - hookTrackingUrl("$MISC_PATH/WatchHistoryPatch;->replaceTrackingUrl(Landroid/net/Uri;)Landroid/net/Uri;") + hookWatchHistory() // region add settings diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/Fingerprints.kt deleted file mode 100644 index 1da109cbe..000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/Fingerprints.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.revanced.patches.youtube.utils.trackingurlhook - -import app.revanced.util.fingerprint.legacyFingerprint -import app.revanced.util.or -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -internal val trackingUrlModelFingerprint = legacyFingerprint( - name = "trackingUrlModelFingerprint", - returnType = "Landroid/net/Uri;", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = emptyList(), - opcodes = listOf( - Opcode.IGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - ), - customFingerprint = { method, _ -> - method.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/player/TrackingUrlModel;" - } -) diff --git a/patches/src/main/resources/music/settings/host/values/arrays.xml b/patches/src/main/resources/music/settings/host/values/arrays.xml index 68fa7ba45..6425d91f1 100644 --- a/patches/src/main/resources/music/settings/host/values/arrays.xml +++ b/patches/src/main/resources/music/settings/host/values/arrays.xml @@ -95,4 +95,14 @@ ANDROID_VR ANDROID_MUSIC + + @string/revanced_watch_history_type_entry_1 + @string/revanced_watch_history_type_entry_2 + @string/revanced_watch_history_type_entry_3 + + + ORIGINAL + REPLACE + BLOCK + diff --git a/patches/src/main/resources/music/settings/host/values/strings.xml b/patches/src/main/resources/music/settings/host/values/strings.xml index fbc3a29db..012bc0f24 100644 --- a/patches/src/main/resources/music/settings/host/values/strings.xml +++ b/patches/src/main/resources/music/settings/host/values/strings.xml @@ -480,6 +480,13 @@ Info: Android Music 5.29.53 iOS Music 6.21 iOS Music 7.04 + Watch history type + "• Original: Follows the watch history settings of Google account, but watch history may not work due to DNS or VPN. +• Replace domain: Follows the watch history settings of Google account. +• Block watch history: Watch history is blocked." + Original + Replace domain + Block watch history Open default app settings To open YouTube Music links in RVX Music, enable Open supported links and enable all the Supported web addresses.