Created
May 10, 2026 10:14
-
-
Save ivan/7dff08893319bd06916781975b4e1ee6 to your computer and use it in GitHub Desktop.
Firefox patch to put the URL in the window title
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js | |
| index 37cbdd29fec4..ddebb1c0ef7a 100644 | |
| --- a/browser/components/tabbrowser/content/tabbrowser.js | |
| +++ b/browser/components/tabbrowser/content/tabbrowser.js | |
| @@ -206,9 +206,6 @@ | |
| "moz-src:///browser/components/tabbrowser/TabMetrics.sys.mjs", | |
| TabStateFlusher: | |
| "resource:///modules/sessionstore/TabStateFlusher.sys.mjs", | |
| - TaskbarTabsUtils: | |
| - "resource:///modules/taskbartabs/TaskbarTabsUtils.sys.mjs", | |
| - TaskbarTabs: "resource:///modules/taskbartabs/TaskbarTabs.sys.mjs", | |
| UrlbarUtils: "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs", | |
| UrlbarProviderOpenTabs: | |
| "moz-src:///browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs", | |
| @@ -1469,201 +1466,31 @@ | |
| } | |
| } | |
| - #cachedTitleInfo = null; | |
| - #populateTitleCache() { | |
| - this.#cachedTitleInfo = {}; | |
| - for (let id of [ | |
| - "mainWindowTitle", | |
| - "privateWindowTitle", | |
| - "privateWindowSuffixForContent", | |
| - ]) { | |
| - this.#cachedTitleInfo[id] = | |
| - document.getElementById(id)?.textContent || ""; | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * The current Taskbar Tab associated with this window. This cannot | |
| - * change after it is first set. | |
| - * | |
| - * @type {TaskbarTab|null} | |
| - */ | |
| - #taskbarTab = null; | |
| - | |
| - /** | |
| - * The last title associated with this window, avoiding re-lookup | |
| - * of the container name and localizations. | |
| - * | |
| - * @type {string|null} | |
| - */ | |
| - #taskbarTabTitle = null; | |
| - | |
| - /** | |
| - * The last profile used when determining the Taskbar Tab title. (This | |
| - * can change, for example if the first profile is made after opening | |
| - * the Taskbar Tab.) | |
| - * | |
| - * @type {string|null} | |
| - */ | |
| - #taskbarTabTitleLastProfile = null; | |
| - | |
| - /** | |
| - * Determines the content of the window title that relates to the Taskbar | |
| - * Tab. This includes the name of the Taskbar Tab, of the container, and | |
| - * of the profile. | |
| - * | |
| - * If no Taskbar Tab is in use, the profile is added by | |
| - * getWindowTitleForBrowser and this returns null. | |
| - * | |
| - * @returns {string|null} The part of the title that was determined from | |
| - * the Taskbar Tab, or null if nothing is needed. | |
| - */ | |
| - #determineTaskbarTabTitle(aProfile) { | |
| - if (!this._shouldExposeContentTitle) { | |
| - // The Taskbar Tab and container info expose what site the user's on. | |
| - return null; | |
| - } | |
| - | |
| - if ( | |
| - this.#taskbarTabTitle && | |
| - this.#taskbarTabTitleLastProfile == aProfile | |
| - ) { | |
| - return this.#taskbarTabTitle; | |
| - } | |
| - | |
| - let id = this.TaskbarTabsUtils.getTaskbarTabIdFromWindow(window); | |
| - if (!id) { | |
| - return null; | |
| - } | |
| - | |
| - if (!this.#taskbarTab) { | |
| - this.TaskbarTabs.getTaskbarTab(id) | |
| - .then(tt => { | |
| - this.#taskbarTab = tt; | |
| - this.updateTitlebar(); | |
| - }) | |
| - .catch(() => { | |
| - // The taskbar tab doesn't exist; leave it as-is. | |
| - }); | |
| - return null; | |
| - } | |
| - | |
| - let containerLabel = this.#taskbarTab.userContextId | |
| - ? ContextualIdentityService.getUserContextLabel( | |
| - this.#taskbarTab.userContextId | |
| - ) | |
| - : ""; | |
| - | |
| - let stringName = "taskbar-tab-title-default"; | |
| - if (containerLabel && aProfile) { | |
| - stringName = "taskbar-tab-title-container-profile"; | |
| - } else if (containerLabel && !aProfile) { | |
| - stringName = "taskbar-tab-title-container"; | |
| - } else if (!containerLabel && aProfile) { | |
| - stringName = "taskbar-tab-title-profile"; | |
| - } | |
| - | |
| - this.#taskbarTabTitle = this.tabLocalization.formatValueSync(stringName, { | |
| - name: this.#taskbarTab.name, | |
| - container: containerLabel, | |
| - profile: aProfile, | |
| - }); | |
| - return this.#taskbarTabTitle; | |
| - } | |
| - | |
| - #determineContentTitle(browser) { | |
| + #determineContentTitleAndUrl(browser) { | |
| let title = ""; | |
| - if ( | |
| - !this._shouldExposeContentTitle || | |
| - (PrivateBrowsingUtils.isWindowPrivate(window) && | |
| - !this._shouldExposeContentTitlePbm) | |
| - ) { | |
| - return title; | |
| - } | |
| + let url = ""; | |
| - let docElement = document.documentElement; | |
| - // If location bar is hidden and the URL type supports a host, | |
| - // add the scheme and host to the title to prevent spoofing. | |
| - // XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239 | |
| try { | |
| - if (docElement.getAttribute("chromehidden").includes("location")) { | |
| - const uri = Services.io.createExposableURI(browser.currentURI); | |
| - let prefix = uri.prePath; | |
| - if (uri.scheme == "about") { | |
| - prefix = uri.spec; | |
| - } else if (uri.scheme == "moz-extension") { | |
| - const ext = WebExtensionPolicy.getByHostname(uri.host); | |
| - if (ext && ext.name) { | |
| - let extensionLabel = document.getElementById( | |
| - "urlbar-label-extension" | |
| - ); | |
| - prefix = `${extensionLabel.value} (${ext.name})`; | |
| - } | |
| - } | |
| - title = prefix + " - "; | |
| - } | |
| + let uri = Services.io.createExposableURI(browser.currentURI); | |
| + url = (uri.displaySpec || uri.spec).replace(/\0/g, ""); | |
| } catch (e) { | |
| // ignored | |
| } | |
| - if (docElement.hasAttribute("titlepreface")) { | |
| - title += docElement.getAttribute("titlepreface"); | |
| - } | |
| - | |
| let tab = this.getTabForBrowser(browser); | |
| if (tab._labelIsContentTitle) { | |
| // Strip out any null bytes in the content title, since the | |
| // underlying widget implementations of nsWindow::SetTitle pass | |
| // null-terminated strings to system APIs. | |
| - title += tab.getAttribute("label").replace(/\0/g, ""); | |
| + title = tab.getAttribute("label").replace(/\0/g, ""); | |
| } | |
| - return title; | |
| + | |
| + return { title, url }; | |
| } | |
| getWindowTitleForBrowser(browser) { | |
| - if (!this.#cachedTitleInfo) { | |
| - this.#populateTitleCache(); | |
| - } | |
| - let contentTitle = this.#determineContentTitle(browser); | |
| - let docElement = document.documentElement; | |
| - let isTemporaryPrivateWindow = | |
| - docElement.getAttribute("privatebrowsingmode") == "temporary"; | |
| - | |
| - let profileIdentifier = | |
| - SelectableProfileService?.isEnabled && | |
| - SelectableProfileService.getCachedProfileCount() > 1 && | |
| - SelectableProfileService.currentProfile?.name.replace(/\0/g, ""); | |
| - // Note that empty/falsy bits get filtered below. | |
| - | |
| - let taskbarTabTitle = this.#determineTaskbarTabTitle(profileIdentifier); | |
| - let parts = [contentTitle, taskbarTabTitle ?? profileIdentifier]; | |
| - | |
| - // On macOS PB windows, add the private window suffix if we have a content | |
| - // title. We'll add the brand name and private window suffix for all other | |
| - // platforms below. | |
| - if ( | |
| - AppConstants.platform == "macosx" && | |
| - contentTitle && | |
| - isTemporaryPrivateWindow | |
| - ) { | |
| - parts.push(this.#cachedTitleInfo.privateWindowSuffixForContent); | |
| - } | |
| - | |
| - // Show the brand name if we aren't a Taskbar Tab, since that is done in | |
| - // #determineTaskbarTabTitle. On macOS we only do this if we don't have a | |
| - // content title; elsewhere, the brand becomes a suffix in the title bar. | |
| - if ( | |
| - !taskbarTabTitle && | |
| - (!contentTitle || AppConstants.platform != "macosx") | |
| - ) { | |
| - parts.push( | |
| - this.#cachedTitleInfo[ | |
| - isTemporaryPrivateWindow ? "privateWindowTitle" : "mainWindowTitle" | |
| - ] | |
| - ); | |
| - } | |
| - | |
| - return parts.filter(p => !!p).join(" — "); | |
| + let { title, url } = this.#determineContentTitleAndUrl(browser); | |
| + return [title, url].filter(p => !!p).join(" - "); | |
| } | |
| updateTitlebar() { | |
| @@ -8549,7 +8376,6 @@ | |
| break; | |
| } | |
| case "intl:app-locales-changed": { | |
| - this.#populateTitleCache(); | |
| this.updateTitlebar(); | |
| break; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment