summaryrefslogtreecommitdiffstats
path: root/browser/modules/TabUnloader.jsm
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--browser/modules/TabUnloader.jsm76
1 files changed, 76 insertions, 0 deletions
diff --git a/browser/modules/TabUnloader.jsm b/browser/modules/TabUnloader.jsm
new file mode 100644
index 0000000000..772c7eac94
--- /dev/null
+++ b/browser/modules/TabUnloader.jsm
@@ -0,0 +1,76 @@
+/* -*- mode: js; indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* 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";
+
+var EXPORTED_SYMBOLS = ["TabUnloader"];
+
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+/**
+ * This module is responsible for detecting low-memory scenarios and unloading
+ * tabs in response to them.
+ */
+
+var TabUnloader = {
+ /**
+ * Initialize low-memory detection and tab auto-unloading.
+ */
+ init() {
+ if (Services.prefs.getBoolPref("browser.tabs.unloadOnLowMemory", true)) {
+ Services.obs.addObserver(this, "memory-pressure", /* ownsWeak */ true);
+ }
+ },
+
+ observe(subject, topic, data) {
+ if (topic == "memory-pressure" && data != "heap-minimize") {
+ unloadLeastRecentlyUsedTab();
+ }
+ },
+
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIObserver",
+ "nsISupportsWeakReference",
+ ]),
+};
+
+function unloadLeastRecentlyUsedTab() {
+ let bgTabBrowsers = getSortedBackgroundTabBrowsers();
+
+ for (let tb of bgTabBrowsers) {
+ if (tb.browser.discardBrowser(tb.tab)) {
+ return;
+ }
+ }
+}
+
+/* Sort tabs in the order we use for unloading, first non-pinned, non-audible
+ * tabs in LRU order, then non-audible tabs in LRU order, then non-pinned
+ * audible tabs in LRU order and finally pinned, audible tabs in LRU order. */
+function sortTabs(a, b) {
+ if (a.tab.soundPlaying != b.tab.soundPlaying) {
+ return a.tab.soundPlaying - b.tab.soundPlaying;
+ }
+
+ if (a.tab.pinned != b.tab.pinned) {
+ return a.tab.pinned - b.tab.pinned;
+ }
+
+ return a.tab.lastAccessed - b.tab.lastAccessed;
+}
+
+function getSortedBackgroundTabBrowsers() {
+ let bgTabBrowsers = [];
+
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ for (let tab of win.gBrowser.tabs) {
+ if (!tab.selected && tab.linkedBrowser.isConnected) {
+ bgTabBrowsers.push({ tab, browser: win.gBrowser });
+ }
+ }
+ }
+
+ return bgTabBrowsers.sort(sortTabs);
+}