mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
bug 1071880 - Notify user of addons that are slowing their browser down significantly r=mossop
This commit is contained in:
parent
7b637b95c2
commit
d9f6139998
@ -138,6 +138,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
|
||||
"resource:///modules/ReaderParent.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AddonWatcher",
|
||||
"resource://gre/modules/AddonWatcher.jsm");
|
||||
|
||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
||||
|
||||
@ -564,6 +567,76 @@ BrowserGlue.prototype = {
|
||||
this._distributionCustomizer.applyPrefDefaults();
|
||||
},
|
||||
|
||||
_notifySlowAddon: function BG_notifySlowAddon(addonId) {
|
||||
let addonCallback = function(addon) {
|
||||
if (!addon) {
|
||||
Cu.reportError("couldn't look up addon: " + addonId);
|
||||
return;
|
||||
}
|
||||
let win = RecentWindow.getMostRecentBrowserWindow();
|
||||
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
let brandBundle = win.document.getElementById("bundle_brand");
|
||||
let brandShortName = brandBundle.getString("brandShortName");
|
||||
let message = win.gNavigatorBundle.getFormattedString("addonwatch.slow", [addon.name, brandShortName]);
|
||||
let notificationBox = win.document.getElementById("global-notificationbox");
|
||||
let notificationId = 'addon-slow:' + addonId;
|
||||
let notification = notificationBox.getNotificationWithValue(notificationId);
|
||||
if(notification) {
|
||||
notification.label = message;
|
||||
} else {
|
||||
let buttons = [
|
||||
{
|
||||
label: win.gNavigatorBundle.getFormattedString("addonwatch.disable.label", [addon.name]),
|
||||
accessKey: win.gNavigatorBundle.getString("addonwatch.disable.accesskey"),
|
||||
callback: function() {
|
||||
addon.userDisabled = true;
|
||||
if (addon.pendingOperations != addon.PENDING_NONE) {
|
||||
let restartMessage = win.gNavigatorBundle.getFormattedString("addonwatch.restart.message", [addon.name, brandShortName]);
|
||||
let restartButton = [
|
||||
{
|
||||
label: win.gNavigatorBundle.getFormattedString("addonwatch.restart.label", [brandShortName]),
|
||||
accessKey: win.gNavigatorBundle.getString("addonwatch.restart.accesskey"),
|
||||
callback: function() {
|
||||
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
|
||||
.getService(Ci.nsIAppStartup);
|
||||
appStartup.quit(appStartup.eForceQuit | appStartup.eRestart);
|
||||
}
|
||||
}
|
||||
];
|
||||
const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
|
||||
notificationBox.appendNotification(restartMessage, "restart-" + addonId, "",
|
||||
priority, restartButton);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: win.gNavigatorBundle.getString("addonwatch.ignoreSession.label"),
|
||||
accessKey: win.gNavigatorBundle.getString("addonwatch.ignoreSession.accesskey"),
|
||||
callback: function() {
|
||||
AddonWatcher.ignoreAddonForSession(addonId);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: win.gNavigatorBundle.getString("addonwatch.ignorePerm.label"),
|
||||
accessKey: win.gNavigatorBundle.getString("addonwatch.ignorePerm.accesskey"),
|
||||
callback: function() {
|
||||
AddonWatcher.ignoreAddonPermanently(addonId);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
|
||||
notificationBox.appendNotification(message, notificationId, "",
|
||||
priority, buttons);
|
||||
}
|
||||
};
|
||||
AddonManager.getAddonByID(addonId, addonCallback);
|
||||
},
|
||||
|
||||
// runs on startup, before the first command line handler is invoked
|
||||
// (i.e. before the first window is opened)
|
||||
_finalUIStartup: function BG__finalUIStartup() {
|
||||
@ -612,6 +685,8 @@ BrowserGlue.prototype = {
|
||||
#endif
|
||||
|
||||
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||
|
||||
AddonWatcher.init(this._notifySlowAddon);
|
||||
},
|
||||
|
||||
_checkForOldBuildUpdates: function () {
|
||||
|
@ -40,6 +40,17 @@ addonDownloadRestart=Restart Download;Restart Downloads
|
||||
addonDownloadRestart.accessKey=R
|
||||
addonDownloadCancelTooltip=Cancel
|
||||
|
||||
addonwatch.slow=%S might be making %S run slowly
|
||||
addonwatch.disable.label=Disable %S
|
||||
addonwatch.disable.accesskey=D
|
||||
addonwatch.ignoreSession.label=Ignore for now
|
||||
addonwatch.ignoreSession.accesskey=I
|
||||
addonwatch.ignorePerm.label=Ignore permanently
|
||||
addonwatch.ignorePerm.accesskey=p
|
||||
addonwatch.restart.message=To disable %S you must restart %S
|
||||
addonwatch.restart.label=Restart %s
|
||||
addonwatch.restart.accesskey=R
|
||||
|
||||
# LOCALIZATION NOTE (addonsInstalled, addonsInstalledNeedsRestart):
|
||||
# Semicolon-separated list of plural forms. See:
|
||||
# http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
|
@ -4465,6 +4465,12 @@ pref("dom.mozSettings.SettingsService.verbose.enabled", false);
|
||||
// readwrite.
|
||||
pref("dom.mozSettings.allowForceReadOnly", false);
|
||||
|
||||
// The interval at which to check for slow running addons
|
||||
pref("browser.addon-watch.interval", 15000);
|
||||
pref("browser.addon-watch.ignore", "[\"mochikit@mozilla.org\"]");
|
||||
// the percentage of time addons are allowed to use without being labeled slow
|
||||
pref("browser.addon-watch.percentage-limit", 1);
|
||||
|
||||
// RequestSync API is disabled by default.
|
||||
pref("dom.requestSync.enabled", false);
|
||||
|
||||
|
83
toolkit/modules/AddonWatcher.jsm
Normal file
83
toolkit/modules/AddonWatcher.jsm
Normal file
@ -0,0 +1,83 @@
|
||||
// -*- 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["AddonWatcher"];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||
"resource://gre/modules/Preferences.jsm");
|
||||
|
||||
let AddonWatcher = {
|
||||
_lastAddonTime: {},
|
||||
_timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
|
||||
_callback: null,
|
||||
_interval: 1500,
|
||||
_ignoreList: null,
|
||||
init: function(callback) {
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._callback = callback;
|
||||
try {
|
||||
this._ignoreList = new Set(JSON.parse(Preferences.get("browser.addon-watch.ignore", null)));
|
||||
} catch (ex) {
|
||||
// probably some malformed JSON, ignore and carry on
|
||||
this._ignoreList = new Set();
|
||||
}
|
||||
this._interval = Preferences.get("browser.addon-watch.interval", 15000);
|
||||
this._timer.initWithCallback(this._checkAddons.bind(this), this._interval, Ci.nsITimer.TYPE_REPEATING_SLACK);
|
||||
},
|
||||
_checkAddons: function() {
|
||||
let compartmentInfo = Cc["@mozilla.org/compartment-info;1"]
|
||||
.getService(Ci.nsICompartmentInfo);
|
||||
let compartments = compartmentInfo.getCompartments();
|
||||
let count = compartments.length;
|
||||
let addons = {};
|
||||
for (let i = 0; i < count; i++) {
|
||||
let compartment = compartments.queryElementAt(i, Ci.nsICompartment);
|
||||
if (compartment.addonId) {
|
||||
if (addons[compartment.addonId]) {
|
||||
addons[compartment.addonId] += compartment.time;
|
||||
} else {
|
||||
addons[compartment.addonId] = compartment.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
let limit = this._interval * Preferences.get("browser.addon-watch.percentage-limit", 75) * 10;
|
||||
for (let addonId in addons) {
|
||||
if (!this._ignoreList.has(addonId)) {
|
||||
if (this._lastAddonTime[addonId] && (addons[addonId] - this._lastAddonTime[addonId]) > limit) {
|
||||
this._callback(addonId);
|
||||
}
|
||||
this._lastAddonTime[addonId] = addons[addonId];
|
||||
}
|
||||
}
|
||||
},
|
||||
ignoreAddonForSession: function(addonid) {
|
||||
this._ignoreList.add(addonid);
|
||||
},
|
||||
ignoreAddonPermanently: function(addonid) {
|
||||
this._ignoreList.add(addonid);
|
||||
try {
|
||||
let ignoreList = JSON.parse(Preferences.get("browser.addon-watch.ignore", "[]"))
|
||||
if (!ignoreList.includes(addonid)) {
|
||||
ignoreList.push(addonid);
|
||||
Preferences.set("browser.addon-watch.ignore", JSON.stringify(ignoreList));
|
||||
}
|
||||
} catch (ex) {
|
||||
Preferences.set("browser.addon-watch.ignore", JSON.stringify([addonid]));
|
||||
}
|
||||
}
|
||||
};
|
@ -12,6 +12,7 @@ MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
|
||||
SPHINX_TREES['toolkit_modules'] = 'docs'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'AddonWatcher.jsm',
|
||||
'Battery.jsm',
|
||||
'BinarySearch.jsm',
|
||||
'BrowserUtils.jsm',
|
||||
|
Loading…
Reference in New Issue
Block a user