Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 22, 2025

Summary

Implements navigation validation in the webview to prevent users from navigating to URLs outside the Home Assistant server domain and handles HTTP errors (404, etc.) by going back and displaying an alert.

Implementation:

  • Domain validation (decidePolicyFor navigationAction): Intercepts user link clicks and blocks navigation to external domains

    • Only validates .linkActivated navigation type (user clicks)
    • Programmatic navigation, back/forward, and special schemes (about:, file:) unaffected
    • Uses URL.baseIsEqual() to compare domains (host, port, scheme)
  • Error handling (decidePolicyFor navigationResponse): Detects HTTP errors (status >= 400)

    • Cancels navigation, calls webView.goBack() if possible
    • Shows alert for both 404s and domain violations
  • Alert presentation (showNavigationErrorAlert()):

    • Prevents duplicate alerts by checking presentedViewController
    • Thread-safe presentation on main queue

Localization:

"alerts.navigation_error.title" = "Navigation Error"
"alerts.navigation_error.message" = "This page cannot be displayed because it's outside your Home Assistant server or the page was not found."

Screenshots

N/A - Alert UI uses standard system presentation

Link to pull request in Documentation repository

Documentation: home-assistant/companion.home-assistant#

Any other notes

No unit tests added - existing test infrastructure focuses on external message handlers and doesn't cover WKNavigationDelegate methods. Manual testing recommended for:

  • External link clicks
  • 404 navigation attempts
  • Internal link navigation (should be unaffected)
  • Back/forward navigation (should be unaffected)
Original prompt

If webviewcontroller navigates to a 404 or any URL that does mot beling to the current activateURL domain, navigate the user back and display an alert


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix webviewcontroller navigation for 404 errors Block external domain navigation and handle 404 errors in webview Dec 22, 2025
Copilot AI requested a review from bgoncal December 22, 2025 18:10
@codecov
Copy link

codecov bot commented Jan 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@2b39b10). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4137   +/-   ##
=======================================
  Coverage        ?   45.04%           
=======================================
  Files           ?      250           
  Lines           ?    14350           
  Branches        ?        0           
=======================================
  Hits            ?     6464           
  Misses          ?     7886           
  Partials        ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bgoncal bgoncal marked this pull request as ready for review January 8, 2026 12:07
Copilot AI review requested due to automatic review settings January 8, 2026 12:07
@bgoncal bgoncal merged commit 8ed3a88 into main Jan 8, 2026
19 checks passed
@bgoncal bgoncal deleted the copilot/handle-webview-404-error branch January 8, 2026 12:07
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements navigation validation and error handling in the webview to prevent external domain navigation and handle HTTP errors. The implementation intercepts user link clicks to block external domains and cancels navigation for HTTP error responses (status >= 400), going back and showing an alert in both cases.

  • Adds domain validation in decidePolicyFor navigationAction to block user clicks on external links
  • Modifies HTTP error handling in decidePolicyFor navigationResponse to cancel navigation and go back
  • Adds localized alert for navigation errors

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
Sources/Shared/Resources/Swiftgen/Strings.swift Auto-generated localization strings for navigation error alert
Sources/App/Resources/en.lproj/Localizable.strings English strings for navigation error alert title and message
Sources/App/WebView/WebViewController.swift Implements domain validation, HTTP error handling with go-back behavior, and alert presentation

"alerts.open_url_from_notification.title" = "Open URL?";
"alerts.prompt.cancel" = "Cancel";
"alerts.prompt.ok" = "OK";
"alerts.navigation_error.message" = "This page cannot be displayed because it's outside your Home Assistant server or the page was not found.";
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message combines two distinct error scenarios (external domain navigation and 404 errors) into a single message. This could be confusing for users since they describe different problems with different causes. Consider either:

  1. Using separate alert messages for external domain vs HTTP error scenarios
  2. Rephrasing the message to be more generic and clear
Suggested change
"alerts.navigation_error.message" = "This page cannot be displayed because it's outside your Home Assistant server or the page was not found.";
"alerts.navigation_error.message" = "This page cannot be displayed due to a navigation error.";

Copilot uses AI. Check for mistakes.
Comment on lines +1355 to +1361
// Normal loading error (not initial URL restoration)
// Cancel the navigation, go back if possible, and show alert
decisionHandler(.cancel)
if webView.canGoBack {
webView.goBack()
}
showNavigationErrorAlert()
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change modifies existing behavior for HTTP error responses. Previously, the error page was allowed to display (with decisionHandler(.allow)). Now, navigation is cancelled and the user is taken back. This could break scenarios where displaying the server's error page is intentional (e.g., custom 404 pages, authentication error pages). Consider whether all HTTP 4xx and 5xx errors should trigger a go-back behavior, or if some status codes should still be allowed to display.

Copilot uses AI. Check for mistakes.
Comment on lines +1386 to +1393
DispatchQueue.main.async { [weak self] in
guard let self else { return }
if presentedViewController != nil {
Current.Log.info("Navigation error alert not shown because another view is already presented")
return
}
present(alert, animated: true)
}
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a potential race condition in alert presentation. Since the alert is shown asynchronously on the main queue, multiple navigation errors in quick succession could attempt to show alerts before the first one is presented. The presentedViewController check on line 1388 might not be effective if called before the first alert's present() completes. Consider adding a flag to track whether an alert is queued for presentation, or debouncing the alert display.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants