-
Notifications
You must be signed in to change notification settings - Fork 15
Deep Link Testing & AASA Validator #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,173 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.Security.Cryptography.Pkcs; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.Text; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.Text.Json; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using MauiSherpa.Core.Interfaces; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace MauiSherpa.Core.Services; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class DeepLinkValidationService : IDeepLinkValidationService | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static readonly HttpClient Http = new() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timeout = TimeSpan.FromSeconds(10) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public async Task<AasaValidationResult> ValidateAppleAppSiteAssociationAsync(string domain) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var url = $"https://{domain}/.well-known/apple-app-site-association"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var response = await Http.GetAsync(url).ConfigureAwait(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+21
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public async Task<AasaValidationResult> ValidateAppleAppSiteAssociationAsync(string domain) | |
| { | |
| try | |
| { | |
| var url = $"https://{domain}/.well-known/apple-app-site-association"; | |
| var response = await Http.GetAsync(url).ConfigureAwait(false); | |
| static bool IsValidHostName(string domain) | |
| { | |
| if (string.IsNullOrWhiteSpace(domain)) | |
| return false; | |
| if (domain.IndexOfAny(['@', '/', '\\', ':', '?', '#']) >= 0) | |
| return false; | |
| return Uri.CheckHostName(domain) != UriHostNameType.Unknown; | |
| } | |
| public async Task<AasaValidationResult> ValidateAppleAppSiteAssociationAsync(string domain) | |
| { | |
| try | |
| { | |
| if (!IsValidHostName(domain)) | |
| { | |
| return new AasaValidationResult( | |
| false, | |
| false, | |
| null, | |
| Array.Empty<AasaAppEntry>(), | |
| "Invalid domain name", | |
| false); | |
| } | |
| var requestUri = new UriBuilder("https", domain) | |
| { | |
| Path = ".well-known/apple-app-site-association" | |
| }.Uri; | |
| var response = await Http.GetAsync(requestUri).ConfigureAwait(false); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -5,6 +5,7 @@ | |||||
| @inject DeviceInspectorService Inspector | ||||||
| @inject IAlertService AlertService | ||||||
| @inject IDialogService DialogService | ||||||
| @inject IDeepLinkValidationService DeepLinkValidator | ||||||
|
||||||
| @inject IDeepLinkValidationService DeepLinkValidator |
Copilot
AI
Apr 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These validation styles (.validation-result, .validation-status, .validation-raw, .deep-link-warning, etc.) are duplicated between DeviceToolsTab and SimToolsTab. Consider moving them into a shared stylesheet (e.g., a common component CSS block or wwwroot CSS) to avoid future drift and reduce maintenance overhead.
Copilot
AI
Apr 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UI messaging indicates assetlinks.json validation requires an https:// URL, but ExtractDomain accepts both http and https. Consider either enforcing https here, or adjusting the user-facing message to match the actual accepted schemes.
| (uri.Scheme == "https" || uri.Scheme == "http")) | |
| uri.Scheme == Uri.UriSchemeHttps) |
Copilot
AI
Apr 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExtractDomain, IsNonWebScheme, and FormatJson are duplicated in both DeviceToolsTab and SimToolsTab. Consider factoring these into a shared helper (e.g., a small static utility in the UI project) so fixes/behavior changes (scheme handling, formatting options, etc.) only need to be made once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new service adds non-trivial parsing/validation logic (AASA modern/legacy formats, signed-vs-raw content, assetlinks relation filtering) but there are no accompanying unit tests under
tests/MauiSherpa.Core.Tests/Services. Adding tests for success, missing/invalid JSON, non-2xx responses, and signed AASA decoding would help prevent regressions. Consider also making the HTTP dependency injectable (instead of a staticHttpClient) to enable deterministic tests.