78 lines
3.4 KiB
C#
78 lines
3.4 KiB
C#
namespace VideoDownloader.Browser;
|
|
|
|
public enum PermissionVerdict { Ask, Allow, Deny }
|
|
|
|
/// <summary>
|
|
/// T3-11 사이트별 권한 정책 — 출처×종류 단위 기억. WebView2 PermissionRequested 에서
|
|
/// Ask 만 프롬프트로 올리고 Allow/Deny 는 즉시 응답. "항상" 선택은 네이티브
|
|
/// Profile.SetPermissionStateAsync 로도 영속(세션 밖 저장).
|
|
/// </summary>
|
|
public sealed class PermissionGate
|
|
{
|
|
/// <summary>프롬프트 없이 거절: 센서류(피싱 표면 축소).</summary>
|
|
private static readonly HashSet<string> AutoDeny = new(StringComparer.OrdinalIgnoreCase) { "OtherSensors" };
|
|
/// <summary>프롬프트 없이 허용: 연속 다운로드(다운로더 앱 본업).</summary>
|
|
private static readonly HashSet<string> AutoAllow = new(StringComparer.OrdinalIgnoreCase) { "MultipleAutomaticDownloads" };
|
|
|
|
private readonly Dictionary<(string origin, string kind), PermissionVerdict> _saved = new();
|
|
|
|
public PermissionVerdict Decide(string kind, string origin)
|
|
{
|
|
if (AutoDeny.Contains(kind)) return PermissionVerdict.Deny;
|
|
if (AutoAllow.Contains(kind)) return PermissionVerdict.Allow;
|
|
return _saved.GetValueOrDefault((origin, kind), PermissionVerdict.Ask);
|
|
}
|
|
|
|
public void Remember(string kind, string origin, PermissionVerdict verdict)
|
|
=> _saved[(origin, kind)] = verdict;
|
|
}
|
|
|
|
/// <summary>T3-14: 추적 스크립트 블랙리스트 — 호스트 또는 서브도메인 매칭.</summary>
|
|
public sealed class TrackerBlocklist
|
|
{
|
|
/// <summary>주요 광고/분석 도메인(EasyList 공통 항목 발췌). 생성자 주입으로 교체 가능(테스트).</summary>
|
|
public static readonly string[] DefaultDomains =
|
|
{
|
|
"google-analytics.com", "googletagmanager.com", "doubleclick.net", "googlesyndication.com",
|
|
"googleadservices.com", "scorecardresearch.com", "hotjar.com", "mixpanel.com", "segment.io",
|
|
"facebook.net", "connect.facebook.net", "amplitude.com", "branch.io", "appsflyer.com",
|
|
"criteo.com", "taboola.com", "outbrain.com", "adnxs.com", "pubmatic.com", "rubiconproject.com",
|
|
};
|
|
|
|
private readonly HashSet<string> _domains;
|
|
|
|
public TrackerBlocklist() : this(DefaultDomains) { }
|
|
public TrackerBlocklist(IEnumerable<string> domains) =>
|
|
_domains = new HashSet<string>(domains, StringComparer.OrdinalIgnoreCase);
|
|
|
|
public bool Matches(Uri url)
|
|
{
|
|
var host = url.Host;
|
|
foreach (var d in _domains)
|
|
if (host.Equals(d, StringComparison.OrdinalIgnoreCase) ||
|
|
host.EndsWith("." + d, StringComparison.OrdinalIgnoreCase))
|
|
return true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>T3-14: 차단 카운터 — 총계/도메인별 집계, 변경 통지(실드 배지 갱신용).</summary>
|
|
public sealed class TrackerCounter
|
|
{
|
|
private int _total;
|
|
public int Total => Volatile.Read(ref _total);
|
|
public Dictionary<string, int> ByDomain { get; } = new(StringComparer.OrdinalIgnoreCase);
|
|
public event Action? Changed;
|
|
|
|
public void Record(string url)
|
|
{
|
|
var host = new Uri(url).Host;
|
|
var baseDomain = host.StartsWith("www.", StringComparison.OrdinalIgnoreCase) ? host[4..] : host;
|
|
Interlocked.Increment(ref _total);
|
|
lock (ByDomain)
|
|
{
|
|
ByDomain[baseDomain] = ByDomain.GetValueOrDefault(baseDomain) + 1;
|
|
}
|
|
Changed?.Invoke();
|
|
}
|
|
}
|