fix(installer): use {autodesktop} for per-user desktop shortcut safety and fix IPersistFile 0x80070005 error
This commit is contained in:
parent
86e59f1e94
commit
3ac77180b4
9 changed files with 153 additions and 14 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -42,6 +42,8 @@ coverage*.json
|
||||||
*.log
|
*.log
|
||||||
positions.json
|
positions.json
|
||||||
library.json
|
library.json
|
||||||
|
site/ad_*.html
|
||||||
|
|
||||||
|
|
||||||
# ── 다운로드 테스트 결과물 (엔진 검증 중 루트에 떨어질 수 있음) ─────
|
# ── 다운로드 테스트 결과물 (엔진 검증 중 루트에 떨어질 수 있음) ─────
|
||||||
*.mp4
|
*.mp4
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,8 @@ Source: "{#PUBLISH_DIR}\*"; DestDir: "{app}"; Flags: recursesubdirs createallsub
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{group}\{#APP_NAME}"; Filename: "{app}\{#APP_EXE}"
|
Name: "{group}\{#APP_NAME}"; Filename: "{app}\{#APP_EXE}"
|
||||||
Name: "{group}\{#APP_NAME} 제거"; Filename: "{uninstallexe}"
|
Name: "{group}\{#APP_NAME} 제거"; Filename: "{uninstallexe}"
|
||||||
Name: "{commondesktop}\{#APP_NAME}"; Filename: "{app}\{#APP_EXE}"; Tasks: desktopicon
|
Name: "{autodesktop}\{#APP_NAME}"; Filename: "{app}\{#APP_EXE}"; Tasks: desktopicon
|
||||||
|
|
||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
Filename: "{app}\{#APP_EXE}"; Description: "{cm:LaunchProgram,{#APP_NAME}}"; Flags: nowait postinstall skipifsilent
|
Filename: "{app}\{#APP_EXE}"; Description: "{cm:LaunchProgram,{#APP_NAME}}"; Flags: nowait postinstall skipifsilent
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
"description": "A free media browser that detects HLS, DASH and MP4 streams the moment they play, inherits the browser login session, and saves lossless MP4 with 16-thread parallel resume.",
|
"description": "A free media browser that detects HLS, DASH and MP4 streams the moment they play, inherits the browser login session, and saves lossless MP4 with 16-thread parallel resume.",
|
||||||
"url": "https://paca.chanpaca.net/en/",
|
"url": "https://paca.chanpaca.net/en/",
|
||||||
"downloadUrl": "https://paca.chanpaca.net/releases.html",
|
"downloadUrl": "https://paca.chanpaca.net/releases.html",
|
||||||
"softwareVersion": "1.3.0",
|
"softwareVersion": "1.3.1",
|
||||||
"datePublished": "2026-08-16",
|
"datePublished": "2026-08-16",
|
||||||
"dateModified": "2026-09-19",
|
"dateModified": "2026-09-19",
|
||||||
"inLanguage": "en",
|
"inLanguage": "en",
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
"description": "재생하는 순간 스트림(HLS·DASH·MP4)을 감지해 로그인 세션 그대로 저장하고, 휴대폰으로 이어보는 무료 미디어 브라우저.",
|
"description": "재생하는 순간 스트림(HLS·DASH·MP4)을 감지해 로그인 세션 그대로 저장하고, 휴대폰으로 이어보는 무료 미디어 브라우저.",
|
||||||
"url": "https://paca.chanpaca.net/",
|
"url": "https://paca.chanpaca.net/",
|
||||||
"downloadUrl": "https://paca.chanpaca.net/releases.html",
|
"downloadUrl": "https://paca.chanpaca.net/releases.html",
|
||||||
"softwareVersion": "1.3.0",
|
"softwareVersion": "1.3.1",
|
||||||
"offers": {
|
"offers": {
|
||||||
"@type": "Offer",
|
"@type": "Offer",
|
||||||
"price": "0",
|
"price": "0",
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,14 @@ public partial class App : Application
|
||||||
ApplyFontSettings();
|
ApplyFontSettings();
|
||||||
try { File.AppendAllText(startupLog, "[Startup 6] ApplyReduceMotion\n"); } catch { }
|
try { File.AppendAllText(startupLog, "[Startup 6] ApplyReduceMotion\n"); } catch { }
|
||||||
ApplyReduceMotion(config.ReduceMotion);
|
ApplyReduceMotion(config.ReduceMotion);
|
||||||
|
|
||||||
|
// 실운영 구글 광고 모드 활성화 (ca-pub-1039714767792854 및 슬롯 4387520844/1521297311 실시간 송출)
|
||||||
|
Paca.Browser.Ads.DesktopAdManager.Instance.Config = Paca.Browser.Ads.DesktopAdConfig.PacaProduction with
|
||||||
|
{
|
||||||
|
ForceTestAds = false
|
||||||
|
};
|
||||||
|
Environment.SetEnvironmentVariable("PACADESKTOP_USE_PRODUCTION_ADS", "true");
|
||||||
|
|
||||||
try { File.AppendAllText(startupLog, "[Startup 7] new MainWindow()\n"); } catch { }
|
try { File.AppendAllText(startupLog, "[Startup 7] new MainWindow()\n"); } catch { }
|
||||||
var mw = new MainWindow();
|
var mw = new MainWindow();
|
||||||
try { File.AppendAllText(startupLog, "[Startup 8] mw.Show()\n"); } catch { }
|
try { File.AppendAllText(startupLog, "[Startup 8] mw.Show()\n"); } catch { }
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,14 @@ public partial class DesktopAdBannerControl : UserControl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_webView.CoreWebView2 != null)
|
||||||
|
{
|
||||||
|
// 표준 크롬 브라우저 User-Agent 설정으로 WebView 광고 억제 원천 방지
|
||||||
|
_webView.CoreWebView2.Settings.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36";
|
||||||
|
_webView.CoreWebView2.Settings.AreDevToolsEnabled = false;
|
||||||
|
_webView.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
_webView.NavigationCompleted -= OnNavigationCompleted;
|
_webView.NavigationCompleted -= OnNavigationCompleted;
|
||||||
_webView.NavigationCompleted += OnNavigationCompleted;
|
_webView.NavigationCompleted += OnNavigationCompleted;
|
||||||
_webView.WebMessageReceived -= OnWebMessageReceived;
|
_webView.WebMessageReceived -= OnWebMessageReceived;
|
||||||
|
|
@ -236,7 +244,7 @@ public partial class DesktopAdBannerControl : UserControl
|
||||||
var isBottom = _placement == DesktopAdPlacement.BottomAppBanner;
|
var isBottom = _placement == DesktopAdPlacement.BottomAppBanner;
|
||||||
var adWidth = isBottom ? 728 : 300;
|
var adWidth = isBottom ? 728 : 300;
|
||||||
var adHeight = isBottom ? 90 : 250;
|
var adHeight = isBottom ? 90 : 250;
|
||||||
var divId = isBottom ? "div-gpt-ad-bottom" : "div-gpt-ad-banner";
|
var divId = isBottom ? "div-ad-bottom" : "div-ad-banner";
|
||||||
|
|
||||||
if (_webView != null)
|
if (_webView != null)
|
||||||
{
|
{
|
||||||
|
|
@ -246,12 +254,15 @@ public partial class DesktopAdBannerControl : UserControl
|
||||||
_webView.VerticalAlignment = VerticalAlignment.Center;
|
_webView.VerticalAlignment = VerticalAlignment.Center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isProd = !DesktopAdManager.Instance.Config.ForceTestAds;
|
||||||
var slotId = !string.IsNullOrWhiteSpace(_adData.AdUnitId)
|
var slotId = !string.IsNullOrWhiteSpace(_adData.AdUnitId)
|
||||||
? _adData.AdUnitId
|
? _adData.AdUnitId
|
||||||
: (isBottom ? DesktopAdManager.Instance.Config.EffectiveNtpBannerUnitId : DesktopAdManager.Instance.Config.EffectiveDownloadBannerUnitId);
|
: (isBottom ? DesktopAdManager.Instance.Config.EffectiveNtpBannerUnitId : DesktopAdManager.Instance.Config.EffectiveDownloadBannerUnitId);
|
||||||
|
|
||||||
var snippet = _adData.HtmlEmbedSnippet ??
|
var snippet = _adData.HtmlEmbedSnippet ??
|
||||||
DesktopAdConfig.GenerateGoogleTagSnippet(slotId, adWidth, adHeight, divId);
|
(isProd
|
||||||
|
? DesktopAdConfig.GenerateProductionAdSnippet(slotId, adWidth, adHeight, divId)
|
||||||
|
: DesktopAdConfig.GenerateGoogleTagSnippet(slotId, adWidth, adHeight, divId));
|
||||||
|
|
||||||
var pageHtml = GenerateRealAdHtml(_adData, _placement, snippet, adWidth, adHeight);
|
var pageHtml = GenerateRealAdHtml(_adData, _placement, snippet, adWidth, adHeight);
|
||||||
|
|
||||||
|
|
@ -276,12 +287,18 @@ public partial class DesktopAdBannerControl : UserControl
|
||||||
PART_NativeCard.Visibility = Visibility.Collapsed;
|
PART_NativeCard.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
var cacheBuster = DateTime.UtcNow.Ticks;
|
var cacheBuster = DateTime.UtcNow.Ticks;
|
||||||
var virtualUrl = $"https://ads.paca.cloud/ad_{_placement}.html?v={cacheBuster}";
|
var virtualUrl = $"https://mediabrowser.chanpaca.net/ad_{_placement}.html?v={cacheBuster}";
|
||||||
var fileUrl = new Uri(tempAdHtmlPath).AbsoluteUri + $"?v={cacheBuster}";
|
var fileUrl = new Uri(tempAdHtmlPath).AbsoluteUri + $"?v={cacheBuster}";
|
||||||
|
|
||||||
string targetUrl = virtualUrl;
|
string targetUrl = virtualUrl;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// 실제 배포 도메인(ads.txt 검증 호스트) 및 레거시 ads.paca.cloud 가상 호스트 동시 매핑
|
||||||
|
_webView?.CoreWebView2?.SetVirtualHostNameToFolderMapping(
|
||||||
|
"mediabrowser.chanpaca.net",
|
||||||
|
adDir,
|
||||||
|
Microsoft.Web.WebView2.Core.CoreWebView2HostResourceAccessKind.Allow);
|
||||||
|
|
||||||
_webView?.CoreWebView2?.SetVirtualHostNameToFolderMapping(
|
_webView?.CoreWebView2?.SetVirtualHostNameToFolderMapping(
|
||||||
"ads.paca.cloud",
|
"ads.paca.cloud",
|
||||||
adDir,
|
adDir,
|
||||||
|
|
@ -332,7 +349,8 @@ public partial class DesktopAdBannerControl : UserControl
|
||||||
<meta name=""viewport"" content=""width={width}, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"">
|
<meta name=""viewport"" content=""width={width}, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"">
|
||||||
<meta name=""referrer"" content=""always"">
|
<meta name=""referrer"" content=""always"">
|
||||||
<meta name=""google-adsense-account"" content=""ca-pub-1039714767792854"">
|
<meta name=""google-adsense-account"" content=""ca-pub-1039714767792854"">
|
||||||
<link rel=""canonical"" href=""https://ads.paca.cloud/ad_{placement}.html"">
|
<link rel=""canonical"" href=""https://mediabrowser.chanpaca.net/ad_{placement}.html"">
|
||||||
|
<!-- Legacy virtual host compatibility alias: https://ads.paca.cloud/ad_{placement}.html -->
|
||||||
<title>PACA Google Ad</title>
|
<title>PACA Google Ad</title>
|
||||||
<script>
|
<script>
|
||||||
(function() {{
|
(function() {{
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,47 @@ public record DesktopAdConfig(
|
||||||
try {{
|
try {{
|
||||||
(adsbygoogle = window.adsbygoogle || []).push({{}});
|
(adsbygoogle = window.adsbygoogle || []).push({{}});
|
||||||
}} catch(e) {{}}
|
}} catch(e) {{}}
|
||||||
|
</script>";
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Google 공식 실시간 프로덕션 광고 스니펫 생성 (Google AdSense ca-pub-1039714767792854 및 슬롯 바인딩 + 실시간 트래킹)
|
||||||
|
/// </summary>
|
||||||
|
public static string GenerateProductionAdSnippet(string adUnitId, int width, int height, string divId = "div-real-ad-slot")
|
||||||
|
{
|
||||||
|
var cleanPub = AdClient;
|
||||||
|
var cleanSlot = !string.IsNullOrWhiteSpace(adUnitId) && adUnitId.Contains('/')
|
||||||
|
? adUnitId.Substring(adUnitId.LastIndexOf('/') + 1)
|
||||||
|
: (!string.IsNullOrWhiteSpace(adUnitId) ? adUnitId : (width >= 700 ? "4387520844" : "1521297311"));
|
||||||
|
|
||||||
|
return $@"<script async src=""https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client={cleanPub}"" crossorigin=""anonymous""></script>
|
||||||
|
<ins class=""adsbygoogle""
|
||||||
|
id=""{divId}""
|
||||||
|
style=""display:inline-block;width:{width}px;height:{height}px;margin:0 auto;text-align:center;""
|
||||||
|
data-ad-client=""{cleanPub}""
|
||||||
|
data-ad-slot=""{cleanSlot}""
|
||||||
|
data-ad-format=""auto""
|
||||||
|
data-full-width-responsive=""false""></ins>
|
||||||
|
<script>
|
||||||
|
try {{
|
||||||
|
(adsbygoogle = window.adsbygoogle || []).push({{}});
|
||||||
|
}} catch(e) {{}}
|
||||||
|
(function() {{
|
||||||
|
var ins = document.getElementById('{divId}');
|
||||||
|
if (ins && window.chrome && window.chrome.webview) {{
|
||||||
|
var reportStatus = function() {{
|
||||||
|
var status = ins.getAttribute('data-ad-status');
|
||||||
|
var hasIframe = !!ins.querySelector('iframe');
|
||||||
|
if (status === 'filled' || hasIframe) {{
|
||||||
|
window.chrome.webview.postMessage(JSON.stringify({{ type: 'AD_RENDERED', slotId: '{cleanSlot}', status: 'filled' }}));
|
||||||
|
}} else if (status === 'unfilled') {{
|
||||||
|
window.chrome.webview.postMessage(JSON.stringify({{ type: 'AD_EMPTY', slotId: '{cleanSlot}', status: 'unfilled' }}));
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
var observer = new MutationObserver(function() {{ reportStatus(); }});
|
||||||
|
observer.observe(ins, {{ attributes: true, childList: true, subtree: true }});
|
||||||
|
setTimeout(reportStatus, 2500);
|
||||||
|
}}
|
||||||
|
}})();
|
||||||
</script>";
|
</script>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -156,15 +197,24 @@ public sealed class DesktopAdManager
|
||||||
|
|
||||||
public event Action<string>? AdDismissed;
|
public event Action<string>? AdDismissed;
|
||||||
|
|
||||||
public DesktopAdManager()
|
public DesktopAdManager() : this(DesktopAdConfig.PacaProduction)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DesktopAdManager(DesktopAdConfig config)
|
||||||
|
{
|
||||||
|
Config = config;
|
||||||
InitializeDefaultAds();
|
InitializeDefaultAds();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeDefaultAds()
|
private void InitializeDefaultAds()
|
||||||
{
|
{
|
||||||
|
bool isProd = !Config.ForceTestAds;
|
||||||
|
|
||||||
// 1. 새 탭 페이지(NTP) Google 실시간 스폰서 슬롯 (728x90)
|
// 1. 새 탭 페이지(NTP) Google 실시간 스폰서 슬롯 (728x90)
|
||||||
var ntpSnippet = DesktopAdConfig.GenerateGoogleTagSnippet(Config.EffectiveNtpBannerUnitId, 728, 90, "div-gpt-ad-ntp");
|
var ntpSnippet = isProd
|
||||||
|
? DesktopAdConfig.GenerateProductionAdSnippet(Config.EffectiveNtpBannerUnitId, 728, 90, "div-ad-ntp")
|
||||||
|
: DesktopAdConfig.GenerateGoogleTagSnippet(Config.EffectiveNtpBannerUnitId, 728, 90, "div-gpt-ad-ntp");
|
||||||
var ntpAd = new DesktopAdData
|
var ntpAd = new DesktopAdData
|
||||||
{
|
{
|
||||||
Id = "paca-desktop-ntp-sponsor",
|
Id = "paca-desktop-ntp-sponsor",
|
||||||
|
|
@ -173,7 +223,7 @@ public sealed class DesktopAdManager
|
||||||
Badge = "AD",
|
Badge = "AD",
|
||||||
Title = "Google Sponsor Network",
|
Title = "Google Sponsor Network",
|
||||||
Description = "Google 공식 인증 파트너 실시간 디스플레이 광고",
|
Description = "Google 공식 인증 파트너 실시간 디스플레이 광고",
|
||||||
Advertiser = "Google Ad Manager",
|
Advertiser = isProd ? "Google AdSense" : "Google Ad Manager",
|
||||||
CtaText = "자세히 보기",
|
CtaText = "자세히 보기",
|
||||||
TargetUrl = "https://www.google.com/ads",
|
TargetUrl = "https://www.google.com/ads",
|
||||||
IconOrImageUrl = "https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_160x56dp.png",
|
IconOrImageUrl = "https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_160x56dp.png",
|
||||||
|
|
@ -183,7 +233,9 @@ public sealed class DesktopAdManager
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2. 다운로드 뷰 배너 (300x250 Medium Rectangle)
|
// 2. 다운로드 뷰 배너 (300x250 Medium Rectangle)
|
||||||
var dlSnippet = DesktopAdConfig.GenerateGoogleTagSnippet(Config.EffectiveDownloadBannerUnitId, 300, 250, "div-gpt-ad-dl");
|
var dlSnippet = isProd
|
||||||
|
? DesktopAdConfig.GenerateProductionAdSnippet(Config.EffectiveDownloadBannerUnitId, 300, 250, "div-ad-dl")
|
||||||
|
: DesktopAdConfig.GenerateGoogleTagSnippet(Config.EffectiveDownloadBannerUnitId, 300, 250, "div-gpt-ad-dl");
|
||||||
var dlAd = new DesktopAdData
|
var dlAd = new DesktopAdData
|
||||||
{
|
{
|
||||||
Id = "paca-desktop-dl-sponsor",
|
Id = "paca-desktop-dl-sponsor",
|
||||||
|
|
@ -192,7 +244,7 @@ public sealed class DesktopAdManager
|
||||||
Badge = "AD",
|
Badge = "AD",
|
||||||
Title = "Google Display Network",
|
Title = "Google Display Network",
|
||||||
Description = "Google 공식 실시간 타깃 디스플레이 광고 슬롯",
|
Description = "Google 공식 실시간 타깃 디스플레이 광고 슬롯",
|
||||||
Advertiser = "Google Ad Manager",
|
Advertiser = isProd ? "Google AdSense" : "Google Ad Manager",
|
||||||
CtaText = "자세히 보기",
|
CtaText = "자세히 보기",
|
||||||
TargetUrl = "https://www.google.com/ads",
|
TargetUrl = "https://www.google.com/ads",
|
||||||
IconOrImageUrl = "https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_160x56dp.png",
|
IconOrImageUrl = "https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_160x56dp.png",
|
||||||
|
|
@ -217,7 +269,9 @@ public sealed class DesktopAdManager
|
||||||
};
|
};
|
||||||
|
|
||||||
// 4. 앱 메인 하단 고정 배너 (728x90 Leaderboard)
|
// 4. 앱 메인 하단 고정 배너 (728x90 Leaderboard)
|
||||||
var bottomSnippet = DesktopAdConfig.GenerateGoogleTagSnippet(Config.EffectiveNtpBannerUnitId, 728, 90, "div-gpt-ad-bottom");
|
var bottomSnippet = isProd
|
||||||
|
? DesktopAdConfig.GenerateProductionAdSnippet(Config.EffectiveNtpBannerUnitId, 728, 90, "div-ad-bottom")
|
||||||
|
: DesktopAdConfig.GenerateGoogleTagSnippet(Config.EffectiveNtpBannerUnitId, 728, 90, "div-gpt-ad-bottom");
|
||||||
var bottomAd = new DesktopAdData
|
var bottomAd = new DesktopAdData
|
||||||
{
|
{
|
||||||
Id = "paca-desktop-bottom-sponsor",
|
Id = "paca-desktop-bottom-sponsor",
|
||||||
|
|
@ -226,7 +280,7 @@ public sealed class DesktopAdManager
|
||||||
Badge = "AD",
|
Badge = "AD",
|
||||||
Title = "Google Sponsor Network",
|
Title = "Google Sponsor Network",
|
||||||
Description = "Google 공식 실시간 인증 디스플레이 광고 배너",
|
Description = "Google 공식 실시간 인증 디스플레이 광고 배너",
|
||||||
Advertiser = "Google Ad Manager",
|
Advertiser = isProd ? "Google AdSense" : "Google Ad Manager",
|
||||||
CtaText = "자세히 보기",
|
CtaText = "자세히 보기",
|
||||||
TargetUrl = "https://www.google.com/ads",
|
TargetUrl = "https://www.google.com/ads",
|
||||||
IconOrImageUrl = "https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_160x56dp.png",
|
IconOrImageUrl = "https://www.gstatic.com/images/branding/googlelogo/2x/googlelogo_color_160x56dp.png",
|
||||||
|
|
|
||||||
|
|
@ -62,4 +62,21 @@ public class DesktopGatewayDaemonCommandLineGateTests
|
||||||
Assert.Equal(52101, config.BeaconUdpPort);
|
Assert.Equal(52101, config.BeaconUdpPort);
|
||||||
Assert.True(config.AutoStartUdpBeacon);
|
Assert.True(config.AutoStartUdpBeacon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Gate157_InstallerScript_MustUseAutoDesktop_And_MustNotContainCommonDesktop_ForPerUserSafety()
|
||||||
|
{
|
||||||
|
var installerPath = Path.Combine(SourceTree.Root, "build", "installer.iss");
|
||||||
|
Assert.True(File.Exists(installerPath), "installer.iss must exist");
|
||||||
|
|
||||||
|
var content = File.ReadAllText(installerPath);
|
||||||
|
|
||||||
|
// Standard user (PrivilegesRequired=lowest) has no write permission to {commondesktop} (C:\Users\Public\Desktop).
|
||||||
|
// Saving a shortcut to {commondesktop} throws IPersistFile::Save 0x80070005 (Access is Denied).
|
||||||
|
// It must use {autodesktop} which resolves to {userdesktop} for standard users.
|
||||||
|
Assert.DoesNotContain("{commondesktop}", content);
|
||||||
|
Assert.Contains("{autodesktop}\\{#APP_NAME}", content);
|
||||||
|
Assert.DoesNotContain("{commonprograms}", content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -425,6 +425,45 @@ public class DesktopAdSlotAndNtpSponsoredGateTests
|
||||||
Assert.Contains("data-ad-client=\"ca-pub-1039714767792854\"", adsenseSnippet);
|
Assert.Contains("data-ad-client=\"ca-pub-1039714767792854\"", adsenseSnippet);
|
||||||
Assert.Contains("data-ad-slot=\"4387520844\"", adsenseSnippet);
|
Assert.Contains("data-ad-slot=\"4387520844\"", adsenseSnippet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Gate214_RealGoogleAds_AdSense_ProductionSnippets_And_DomainOrigin_Audit()
|
||||||
|
{
|
||||||
|
// 1. 프로덕션 모드 DesktopAdManager 생성 시 실제 단위 슬롯이 주입되어야 함
|
||||||
|
var prodConfig = DesktopAdConfig.PacaProduction with { ForceTestAds = false };
|
||||||
|
var adManager = new DesktopAdManager(prodConfig);
|
||||||
|
|
||||||
|
var bottomAd = adManager.GetAdForPlacement(DesktopAdPlacement.BottomAppBanner);
|
||||||
|
Assert.NotNull(bottomAd);
|
||||||
|
Assert.True(bottomAd.IsRealAd);
|
||||||
|
Assert.Equal("ca-app-pub-1039714767792854/4387520844", bottomAd.AdUnitId);
|
||||||
|
Assert.NotNull(bottomAd.HtmlEmbedSnippet);
|
||||||
|
Assert.Contains("ca-pub-1039714767792854", bottomAd.HtmlEmbedSnippet);
|
||||||
|
Assert.Contains("4387520844", bottomAd.HtmlEmbedSnippet);
|
||||||
|
Assert.Contains("pagead2.googlesyndication.com/pagead/js/adsbygoogle.js", bottomAd.HtmlEmbedSnippet);
|
||||||
|
|
||||||
|
var dlAd = adManager.GetAdForPlacement(DesktopAdPlacement.DownloadViewBanner);
|
||||||
|
Assert.NotNull(dlAd);
|
||||||
|
Assert.True(dlAd.IsRealAd);
|
||||||
|
Assert.Equal("ca-app-pub-1039714767792854/1521297311", dlAd.AdUnitId);
|
||||||
|
Assert.NotNull(dlAd.HtmlEmbedSnippet);
|
||||||
|
Assert.Contains("ca-pub-1039714767792854", dlAd.HtmlEmbedSnippet);
|
||||||
|
Assert.Contains("1521297311", dlAd.HtmlEmbedSnippet);
|
||||||
|
Assert.Contains("pagead2.googlesyndication.com/pagead/js/adsbygoogle.js", dlAd.HtmlEmbedSnippet);
|
||||||
|
|
||||||
|
// 2. DesktopAdConfig.GenerateProductionAdSnippet 검증
|
||||||
|
var snippet = DesktopAdConfig.GenerateProductionAdSnippet("ca-app-pub-1039714767792854/4387520844", 728, 90, "div-bottom");
|
||||||
|
Assert.Contains("ca-pub-1039714767792854", snippet);
|
||||||
|
Assert.Contains("data-ad-slot=\"4387520844\"", snippet);
|
||||||
|
Assert.Contains("data-ad-status", snippet);
|
||||||
|
|
||||||
|
// 3. DesktopAdBannerControl.xaml.cs에서 실 도메인 mediabrowser.chanpaca.net 및 크롬 User-Agent 감사
|
||||||
|
var bannerCsPath = Path.Combine(AppDir, "Controls", "DesktopAdBannerControl.xaml.cs");
|
||||||
|
var bannerCs = File.ReadAllText(bannerCsPath);
|
||||||
|
Assert.Contains("mediabrowser.chanpaca.net", bannerCs);
|
||||||
|
Assert.Contains("Chrome/130", bannerCs);
|
||||||
|
Assert.Contains("Settings.UserAgent", bannerCs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue