host (macOS): an iframe's navigation no longer becomes the tab's address

wry asks the navigation handler for every WKNavigationAction, iframes included, so an embedded
player (Chat+ link previews' YouTube frame) put its URL in the address bar and left the tab loading
forever. macOS now does the page-level work from on_page_load (Started), the main frame only, as
Linux already did. Verified live: the player plays, the address stays on x.com, no spinner.
This commit is contained in:
CRTkafa 2026-10-15 05:45:42 +08:00
parent 7cf4c81e30
commit ee0dc35363

View file

@ -1046,8 +1046,9 @@ async fn open_panel(webview: Webview, app: AppHandle, section: Option<String>) -
// ---------------------------------------------------------------------------------------------
// Tab webviews
/// Linux: the page-level part of a tab's `on_navigation`, run when the main frame starts loading
/// `url` (WebKitGTK's navigation callback cannot tell iframes from the page). Returns false when
/// Linux and macOS: the page-level part of a tab's `on_navigation`, run when the main frame starts
/// loading `url` (WebKitGTK's navigation callback, and wry's WKWebView one, cannot tell iframes from
/// the page). Returns false when
/// the load was redirected (a legacy domain) or stopped and handed to the browser.
fn main_frame_started(app: &AppHandle, site: &SiteSpec, hooks: &dyn SiteHooks, tab: &Webview, url: &Url) -> bool {
static ON_SITE: std::sync::OnceLock<Mutex<HashMap<String, bool>>> = std::sync::OnceLock::new();
@ -1105,8 +1106,8 @@ fn tab_builder(app: &AppHandle, hooks: &Arc<dyn SiteHooks>, tab: &NewTab, url: U
if url.scheme() == "about" {
return true;
}
// WebKitGTK: possibly an iframe's own document (see below).
if cfg!(target_os = "linux") && matches!(url.scheme(), "blob" | "data") {
// WebKit (GTK and macOS): possibly an iframe's own document (see below).
if cfg!(any(target_os = "linux", target_os = "macos")) && matches!(url.scheme(), "blob" | "data") {
return true;
}
open_external(app, url);
@ -1116,7 +1117,10 @@ fn tab_builder(app: &AppHandle, hooks: &Arc<dyn SiteHooks>, tab: &NewTab, url: U
// asks only for the page): a signed-out page embedding a sign-in iframe would get that
// iframe's URL as the tab's address. On Linux the page-level work below runs from
// on_page_load (Started), which is the main frame only.
if cfg!(target_os = "linux") {
// macOS: wry asks this for every WKNavigationAction, iframes included (no targetFrame
// check), so an embedded player's URL became the tab's address and its loading flag never
// cleared (found 2026-10-11 with Chat+ link previews' YouTube frame). Same treatment.
if cfg!(any(target_os = "linux", target_os = "macos")) {
return true;
}
if let Some(site_url) = nav_hooks.canonical_url(url) {
@ -1157,7 +1161,7 @@ fn tab_builder(app: &AppHandle, hooks: &Arc<dyn SiteHooks>, tab: &NewTab, url: U
})
.on_page_load(move |tab, payload| {
let app = &load_app;
if cfg!(target_os = "linux")
if cfg!(any(target_os = "linux", target_os = "macos"))
&& matches!(payload.event(), PageLoadEvent::Started)
&& !main_frame_started(app, site, &*load_hooks, &tab, payload.url())
{