feat(YouTube Music): Add Check watch history domain name resolution (#5979)

This commit is contained in:
LisoUseInAIKyrios
2025-09-23 13:34:00 +04:00
committed by GitHub
parent 191b9169ff
commit 8af70fe2d1
11 changed files with 118 additions and 44 deletions

View File

@@ -0,0 +1,98 @@
package app.revanced.extension.shared.patches;
import static app.revanced.extension.shared.StringRef.str;
import android.app.Activity;
import android.app.Dialog;
import android.text.Html;
import android.util.Pair;
import android.widget.LinearLayout;
import java.net.InetAddress;
import java.net.UnknownHostException;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.ui.CustomDialog;
@SuppressWarnings("unused")
public class CheckWatchHistoryDomainNameResolutionPatch {
private static final String HISTORY_TRACKING_ENDPOINT = "s.youtube.com";
private static final String SINKHOLE_IPV4 = "0.0.0.0";
private static final String SINKHOLE_IPV6 = "::";
private static boolean domainResolvesToValidIP(String host) {
try {
InetAddress address = InetAddress.getByName(host);
String hostAddress = address.getHostAddress();
if (address.isLoopbackAddress()) {
Logger.printDebug(() -> host + " resolves to localhost");
} else if (SINKHOLE_IPV4.equals(hostAddress) || SINKHOLE_IPV6.equals(hostAddress)) {
Logger.printDebug(() -> host + " resolves to sinkhole ip");
} else {
return true; // Domain is not blocked.
}
} catch (UnknownHostException e) {
Logger.printDebug(() -> host + " failed to resolve");
}
return false;
}
/**
* Injection point.
*
* Checks if s.youtube.com is blacklisted and playback history will fail to work.
*/
public static void checkDnsResolver(Activity context) {
if (!Utils.isNetworkConnected() || !BaseSettings.CHECK_WATCH_HISTORY_DOMAIN_NAME.get()) return;
Utils.runOnBackgroundThread(() -> {
try {
// If the user has a flaky DNS server, or they just lost internet connectivity
// and the isNetworkConnected() check has not detected it yet (it can take a few
// seconds after losing connection), then the history tracking endpoint will
// show a resolving error but it's actually an internet connection problem.
//
// Prevent this false positive by verify youtube.com resolves.
// If youtube.com does not resolve, then it's not a watch history domain resolving error
// because the entire app will not work since no domains are resolving.
if (!domainResolvesToValidIP("youtube.com")
|| domainResolvesToValidIP(HISTORY_TRACKING_ENDPOINT)) {
return;
}
Utils.runOnMainThread(() -> {
try {
// Create the custom dialog.
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
context,
str("revanced_check_watch_history_domain_name_dialog_title"), // Title.
Html.fromHtml(str("revanced_check_watch_history_domain_name_dialog_message")), // Message (HTML).
null, // No EditText.
null, // OK button text.
() -> {}, // OK button action (just dismiss).
() -> {}, // Cancel button action (just dismiss).
str("revanced_check_watch_history_domain_name_dialog_ignore"), // Neutral button text.
() -> BaseSettings.CHECK_WATCH_HISTORY_DOMAIN_NAME.save(false), // Neutral button action (Ignore).
true // Dismiss dialog on Neutral button click.
);
// Show the dialog.
Dialog dialog = dialogPair.first;
Utils.showDialog(context, dialog, false, null);
} catch (Exception ex) {
Logger.printException(() -> "checkDnsResolver dialog creation failure", ex);
}
});
} catch (Exception ex) {
Logger.printException(() -> "checkDnsResolver failure", ex);
}
});
}
}

View File

@@ -28,10 +28,16 @@ public class BaseSettings {
public static final BooleanSetting SETTINGS_SEARCH_HISTORY = new BooleanSetting("revanced_settings_search_history", TRUE, true);
public static final StringSetting SETTINGS_SEARCH_ENTRIES = new StringSetting("revanced_settings_search_entries", "");
//
// Settings shared by YouTube and YouTube Music.
//
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
public static final EnumSetting<AppLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE, parent(SPOOF_VIDEO_STREAMS));
public static final BooleanSetting SANITIZE_SHARED_LINKS = new BooleanSetting("revanced_sanitize_sharing_links", TRUE);
public static final BooleanSetting REPLACE_MUSIC_LINKS_WITH_YOUTUBE = new BooleanSetting("revanced_replace_music_with_youtube", FALSE);
public static final BooleanSetting CHECK_WATCH_HISTORY_DOMAIN_NAME = new BooleanSetting("revanced_check_watch_history_domain_name", TRUE, false, false);
}