diff --git a/app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java new file mode 100644 index 00000000..ca523a4d --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java @@ -0,0 +1,90 @@ +package app.revanced.integrations.patches; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.shared.PlayerType; +import app.revanced.integrations.utils.LogHelper; + +import static app.revanced.integrations.utils.ReVancedUtils.containsAny; + +/** @noinspection unused*/ +public class SpoofSignaturePatch { + /** + * Parameter (also used by + * yt-dlp) + * to fix playback issues. + */ + private static final String INCOGNITO_PARAMETERS = "CgIQBg=="; + + /** + * Parameters causing playback issues. + */ + private static final String[] AUTOPLAY_PARAMETERS = { + "YAHI", // Autoplay in feed. + "SAFg" // Autoplay in scrim. + }; + + /** + * Parameter used for autoplay in scrim. + * Prepend this parameter to mute video playback (for autoplay in feed). + */ + private static final String SCRIM_PARAMETER = "SAFgAXgB"; + + + /** + * Parameters used in YouTube Shorts. + */ + private static final String SHORTS_PLAYER_PARAMETERS = "8AEB"; + + private static boolean isPlayingShorts; + + /** + * Injection point. + * + * @param parameters Original protobuf parameter value. + */ + public static String spoofParameter(String parameters) { + LogHelper.printDebug(() -> "Original protobuf parameter value: " + parameters); + + if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return parameters; + + // Shorts do not need to be spoofed. + //noinspection AssignmentUsedAsCondition + if (isPlayingShorts = parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters; + + boolean isPlayingFeed = PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL && containsAny(parameters, AUTOPLAY_PARAMETERS); + if (isPlayingFeed) return SettingsEnum.SPOOF_SIGNATURE_IN_FEED.getBoolean() ? + // Prepend the scrim parameter to mute videos in feed. + SCRIM_PARAMETER + INCOGNITO_PARAMETERS : + // In order to prevent videos that are auto-played in feed to be added to history, + // only spoof the parameter if the video is not playing in the feed. + // This will cause playback issues in the feed, but it's better than manipulating the history. + parameters; + + return INCOGNITO_PARAMETERS; + } + + /** + * Injection point. + */ + public static boolean getSeekbarThumbnailOverrideValue() { + return SettingsEnum.SPOOF_SIGNATURE.getBoolean(); + } + + /** + * Injection point. + * + * @param view seekbar thumbnail view. Includes both shorts and regular videos. + */ + public static void seekbarImageViewCreated(ImageView view) { + if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return; + if (isPlayingShorts) return; + + view.setVisibility(View.GONE); + // Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible). + ViewGroup parentLayout = (ViewGroup) view.getParent(); + parentLayout.setPadding(0, 0, 0, 0); + } +} diff --git a/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java b/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java deleted file mode 100644 index 37c7a51d..00000000 --- a/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java +++ /dev/null @@ -1,95 +0,0 @@ -package app.revanced.integrations.patches; - -import static app.revanced.integrations.utils.ReVancedUtils.containsAny; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; - -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.shared.PlayerType; -import app.revanced.integrations.utils.LogHelper; - -public class SpoofSignatureVerificationPatch { - /** - * Enable/disable all workarounds that are required due to signature spoofing. - */ - private static final boolean WORKAROUND = true; - - /** - * Protobuf parameters used for autoplay in scrim. - * Prepend this parameter to mute video playback (for autoplay in feed) - */ - private static final String PROTOBUF_PARAMETER_SCRIM = "SAFgAXgB"; - - /** - * Protobuf parameter also used by - * yt-dlp - *
- * Known issue: captions are positioned on upper area in the player. - */ - private static final String PROTOBUF_PLAYER_PARAMS = "CgIQBg=="; - - /** - * Target Protobuf parameters. - */ - private static final String[] PROTOBUF_PARAMETER_TARGETS = { - "YAHI", // Autoplay in feed - "SAFg" // Autoplay in scrim - }; - - /** - * Injection point. - * - * @param originalValue originalValue protobuf parameter - */ - public static String overrideProtobufParameter(String originalValue) { - try { - if (!SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean()) { - return originalValue; - } - - LogHelper.printDebug(() -> "Original protobuf parameter value: " + originalValue); - - if (!WORKAROUND) return PROTOBUF_PLAYER_PARAMS; - - var isPlayingVideo = originalValue.contains(PROTOBUF_PLAYER_PARAMS); - if (isPlayingVideo) return originalValue; - - boolean isPlayingFeed = containsAny(originalValue, PROTOBUF_PARAMETER_TARGETS) && PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL; - if (isPlayingFeed) { - // Videos in feed won't autoplay with sound. - return PROTOBUF_PARAMETER_SCRIM + PROTOBUF_PLAYER_PARAMS; - } else { - // Spoof the parameter to prevent playback issues. - return PROTOBUF_PLAYER_PARAMS; - } - } catch (Exception ex) { - LogHelper.printException(() -> "overrideProtobufParameter failure", ex); - } - - return originalValue; - } - - /** - * Injection point. - */ - public static boolean getSeekbarThumbnailOverrideValue() { - return SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean(); - } - - /** - * Injection point. - * - * @param view seekbar thumbnail view. Includes both shorts and regular videos. - */ - public static void seekbarImageViewCreated(ImageView view) { - if (SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean()) { - view.setVisibility(View.GONE); - // Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible). - ViewGroup parentLayout = (ViewGroup) view.getParent(); - parentLayout.setPadding(0, 0, 0, 0); - } - } - -} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 7b578a63..3ab42ddd 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -165,8 +165,10 @@ public enum SettingsEnum { EXTERNAL_BROWSER("revanced_external_browser", BOOLEAN, TRUE, true), AUTO_REPEAT("revanced_auto_repeat", BOOLEAN, FALSE), SEEKBAR_TAPPING("revanced_seekbar_tapping", BOOLEAN, TRUE), - SPOOF_SIGNATURE_VERIFICATION("revanced_spoof_signature_verification", BOOLEAN, TRUE, true, - "revanced_spoof_signature_verification_user_dialog_message"), + SPOOF_SIGNATURE("revanced_spoof_signature_verification_enabled", BOOLEAN, TRUE, true, + "revanced_spoof_signature_verification_enabled_user_dialog_message"), + SPOOF_SIGNATURE_IN_FEED("revanced_spoof_signature_in_feed_enabled", BOOLEAN, FALSE, false, + parents(SPOOF_SIGNATURE)), // Swipe controls SWIPE_BRIGHTNESS("revanced_swipe_brightness", BOOLEAN, TRUE),