Propagate page title and favicon into the active tab
Servo already publishes the live page title in every `LiveFrameReport` but the renderer was dropping it on the floor — tabs that navigated away from `ely://new-tab` kept showing "New Tab" forever, and there was no favicon visible anywhere in the sidebar. Add `BrowserCore::set_tab_title` and switch `set_tab_favicon_key` to return `Ok(true)` only when the value actually changed; both methods mirror the new value into the matching history entry so the History page stays in lockstep. Derive the canonical `/favicon.ico` URL from the loaded URL on `UrlText` and store it as the tab's `favicon_key`. In the surface layer, every Ready frame now emits a `WebSurfacePageMetadata` change alongside any `WebSurfaceUrlChange`, and the controller applies title + favicon URL together. Render the sidebar tab row's favicon via GPUI's HTTP image loader (falling through to the URL-derived glyph for `ely://` pages, file URLs, and hosts without a /favicon.ico endpoint).
This commit is contained in:
@@ -17,6 +17,33 @@ use super::{
|
||||
},
|
||||
};
|
||||
|
||||
/// One page's worth of metadata observed in a Ready frame. The
|
||||
/// controller applies these to the `BrowserTab` (title / favicon_key)
|
||||
/// after the frame has been swapped into the surface state. Title and
|
||||
/// favicon are independent — a navigation typically settles the URL
|
||||
/// first, then Servo emits a title change a frame or two later, and
|
||||
/// the favicon URL is derived from the loaded URL.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub(super) struct WebSurfacePageMetadata {
|
||||
pub(super) tab_id: TabId,
|
||||
pub(super) title: Option<String>,
|
||||
pub(super) favicon_url: Option<String>,
|
||||
}
|
||||
|
||||
impl WebSurfacePageMetadata {
|
||||
fn from_frame(tab_id: &TabId, frame: &WebSurfaceFrame) -> Option<Self> {
|
||||
let title = frame.title().map(str::to_string);
|
||||
let favicon_url = frame
|
||||
.loaded_url()
|
||||
.and_then(|loaded| ely_domain::UrlText::parse(loaded).ok())
|
||||
.and_then(|url| url.favicon_url());
|
||||
if title.is_none() && favicon_url.is_none() {
|
||||
return None;
|
||||
}
|
||||
Some(Self { tab_id: tab_id.clone(), title, favicon_url })
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct WebSurfaceStore {
|
||||
runtime: WebSurfaceRuntime,
|
||||
/// Single owner of every per-tab invariant. See [`PerTabSurface`].
|
||||
@@ -108,6 +135,9 @@ impl WebSurfaceStore {
|
||||
result.changed = true;
|
||||
continue;
|
||||
}
|
||||
if let Some(metadata) = WebSurfacePageMetadata::from_frame(&tab_id, &frame) {
|
||||
result.page_metadata.push(metadata);
|
||||
}
|
||||
self.surface_mut(&tab_id).state = Some(WebSurfaceState::Ready(*frame));
|
||||
result.changed = true;
|
||||
if let Some(url_change) = url_change {
|
||||
@@ -441,6 +471,7 @@ pub(super) struct WebSurfaceEnsureOutcome {
|
||||
pub(super) struct WebSurfaceTickResult {
|
||||
pub(super) changed: bool,
|
||||
pub(super) url_changes: Vec<WebSurfaceUrlChange>,
|
||||
pub(super) page_metadata: Vec<WebSurfacePageMetadata>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user