gecko-dev/browser/modules/TabUnloader.jsm
Gabriele Svelto 5bc9e5bb2b Bug 675539 - Unload tabs in low-memory scenarios r=mconley
This adds a mechanism that discards tabs when the browser detects a low-memory
scenario. Tabs are discarded in LRU order prioritizing regular tabs over
pinned ones, pinned ones over tabs playing audio and all of the previous over
pinned tabs playing audio.

Differential Revision: https://phabricator.services.mozilla.com/D20476

--HG--
extra : moz-landing-system : lando
2019-02-27 22:24:27 +00:00

77 lines
2.1 KiB
JavaScript

/* -*- 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([
Ci.nsIObserver,
Ci.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);
}