summaryrefslogtreecommitdiffstats
path: root/browser/components/tabunloader/content/aboutUnloads.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/tabunloader/content/aboutUnloads.js')
-rw-r--r--browser/components/tabunloader/content/aboutUnloads.js126
1 files changed, 126 insertions, 0 deletions
diff --git a/browser/components/tabunloader/content/aboutUnloads.js b/browser/components/tabunloader/content/aboutUnloads.js
new file mode 100644
index 0000000000..b58cd83609
--- /dev/null
+++ b/browser/components/tabunloader/content/aboutUnloads.js
@@ -0,0 +1,126 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const { TabUnloader } = ChromeUtils.import(
+ "resource:///modules/TabUnloader.jsm"
+);
+
+async function refreshData() {
+ const sortedTabs = await TabUnloader.getSortedTabs(null);
+ const tabTable = document.querySelector(".tab-table > tbody");
+ const getHost = uri => {
+ try {
+ return uri?.host;
+ } catch (e) {
+ return uri?.spec;
+ }
+ };
+ const updateTimestamp = () => {
+ document.l10n.setAttributes(
+ document.getElementById("label-last-updated"),
+ "about-unloads-last-updated",
+ { date: Date.now() }
+ );
+ };
+
+ // Reset the table
+ // Don't delete the first row showing the "no unloadable tab" message
+ while (tabTable.rows.length > 1) {
+ tabTable.deleteRow(1);
+ }
+ if (!sortedTabs.length) {
+ document.getElementById("button-unload").disabled = true;
+ document.getElementById("no-unloadable-tab-message").hidden = false;
+ updateTimestamp();
+ return;
+ }
+ document.getElementById("button-unload").disabled =
+ !TabUnloader.isDiscardable(sortedTabs[0]);
+ document.getElementById("no-unloadable-tab-message").hidden = true;
+
+ const fragmentRows = new DocumentFragment();
+ const templateRow = document.querySelector("template[name=tab-table-row]");
+
+ let ordinal = 0;
+ for (const tabInfo of sortedTabs) {
+ if (!("tab" in tabInfo)) {
+ continue;
+ }
+
+ const fragment = templateRow.content.cloneNode(true);
+ const row = fragment.querySelector("tr");
+
+ row.children[0].textContent = TabUnloader.isDiscardable(tabInfo)
+ ? ++ordinal
+ : "-";
+ row.children[1].textContent = getHost(
+ tabInfo.tab?.linkedBrowser?.currentURI
+ );
+ if ("lastAccessed" in tabInfo.tab) {
+ document.l10n.setAttributes(
+ row.children[2],
+ "about-unloads-last-accessed",
+ { date: tabInfo.tab.lastAccessed }
+ );
+ }
+ row.children[3].textContent = tabInfo.weight;
+ row.children[4].textContent = tabInfo.sortWeight;
+ if ("memory" in tabInfo) {
+ document.l10n.setAttributes(
+ row.children[5],
+ "about-unloads-memory-in-mb",
+ { mem: tabInfo.memory / 1024 / 1024 }
+ );
+ }
+
+ if (tabInfo.processes) {
+ for (const [pid, procEntry] of tabInfo.processes) {
+ if (pid < 0) {
+ // Tab is hosted by the main process
+ continue;
+ }
+
+ const procLabel = document.createElement("span");
+ const procInfo = procEntry.entryToProcessMap;
+
+ if (procEntry.isTopLevel) {
+ procLabel.classList.add("top-level-process");
+ }
+ if (procInfo.tabSet.size > 1) {
+ procLabel.classList.add("shared-process");
+ }
+ procLabel.textContent = pid;
+ document.l10n.setAttributes(
+ procLabel,
+ "about-unloads-memory-in-mb-tooltip",
+ { mem: procInfo.memory / 1024 / 1024 }
+ );
+ row.children[6].appendChild(procLabel);
+ row.children[6].appendChild(document.createTextNode(" "));
+ }
+ }
+
+ fragmentRows.appendChild(fragment);
+ }
+
+ tabTable.appendChild(fragmentRows);
+ updateTimestamp();
+}
+
+async function onLoad() {
+ document
+ .getElementById("button-unload")
+ .addEventListener("click", async () => {
+ await TabUnloader.unloadLeastRecentlyUsedTab(null);
+ await refreshData();
+ });
+ await refreshData();
+}
+
+try {
+ document.addEventListener("DOMContentLoaded", onLoad, { once: true });
+} catch (ex) {
+ console.error(ex);
+}