diff options
Diffstat (limited to '')
-rw-r--r-- | browser/modules/TabUnloader.jsm | 76 |
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); +} |