Bug 1154465 - Fix add-on shim telemetry (r=gabor)

This commit is contained in:
Bill McCloskey 2015-04-14 13:48:50 -07:00
parent bc4ddb96ea
commit 5dd19bb438
2 changed files with 61 additions and 35 deletions

View File

@ -22,15 +22,12 @@ function section(number, url)
}
let CompatWarning = {
warn: function(msg, addon, warning) {
if (addon) {
let histogram = Services.telemetry.getKeyedHistogramById("ADDON_SHIM_USAGE");
histogram.add(addon, warning ? warning.number : 0);
}
if (!Preferences.get("dom.ipc.shims.enabledWarnings", false))
return;
// Sometimes we want to generate a warning, but put off issuing it
// until later. For example, if someone registers a listener, we
// might only want to warn about it if the listener actually
// fires. However, we want the warning to show a stack for the
// registration site.
delayedWarning: function(msg, addon, warning) {
function isShimLayer(filename) {
return filename.indexOf("CompatWarning.jsm") != -1 ||
filename.indexOf("RemoteAddonsParent.jsm") != -1 ||
@ -42,25 +39,47 @@ let CompatWarning = {
while (stack && isShimLayer(stack.filename))
stack = stack.caller;
let error = Cc['@mozilla.org/scripterror;1'].createInstance(Ci.nsIScriptError);
if (!error || !Services.console) {
// Too late during shutdown to use the nsIConsole
return;
}
let alreadyWarned = false;
let message = `Warning: ${msg}`;
if (warning)
message += `\nMore info at: ${url}`;
return function() {
if (alreadyWarned) {
return;
}
alreadyWarned = true;
error.init(
/*message*/ message,
/*sourceName*/ stack ? stack.filename : "",
/*sourceLine*/ stack ? stack.sourceLine : "",
/*lineNumber*/ stack ? stack.lineNumber : 0,
/*columnNumber*/ 0,
/*flags*/ Ci.nsIScriptError.warningFlag,
/*category*/ "chrome javascript");
Services.console.logMessage(error);
if (addon) {
let histogram = Services.telemetry.getKeyedHistogramById("ADDON_SHIM_USAGE");
histogram.add(addon, warning ? warning.number : 0);
}
if (!Preferences.get("dom.ipc.shims.enabledWarnings", false))
return;
let error = Cc['@mozilla.org/scripterror;1'].createInstance(Ci.nsIScriptError);
if (!error || !Services.console) {
// Too late during shutdown to use the nsIConsole
return;
}
let message = `Warning: ${msg}`;
if (warning)
message += `\nMore info at: ${warning.url}`;
error.init(
/*message*/ message,
/*sourceName*/ stack ? stack.filename : "",
/*sourceLine*/ stack ? stack.sourceLine : "",
/*lineNumber*/ stack ? stack.lineNumber : 0,
/*columnNumber*/ 0,
/*flags*/ Ci.nsIScriptError.warningFlag,
/*category*/ "chrome javascript");
Services.console.logMessage(error);
};
},
warn: function(msg, addon, warning) {
let delayed = this.delayedWarning(msg, addon, warning);
delayed();
},
warnings: {

View File

@ -375,11 +375,12 @@ let ObserverInterposition = new Interposition("ObserverInterposition");
ObserverInterposition.methods.addObserver =
function(addon, target, observer, topic, ownsWeak) {
if (TOPIC_WHITELIST.indexOf(topic) >= 0) {
CompatWarning.warn(`${topic} observer should be added from the child process only.`,
addon, CompatWarning.warnings.observers);
ObserverParent.addObserver(addon, observer, topic);
}
CompatWarning.warn(`${topic} observer should be added from the child process only.`,
addon, CompatWarning.warnings.observers);
target.addObserver(observer, topic, ownsWeak);
};
@ -446,7 +447,7 @@ let EventTargetParent = {
return [browser, window];
},
addEventListener: function(addon, target, type, listener, useCapture, wantsUntrusted) {
addEventListener: function(addon, target, type, listener, useCapture, wantsUntrusted, delayedWarning) {
let newTarget = this.redirectEventTarget(target);
if (!newTarget) {
return;
@ -477,7 +478,8 @@ let EventTargetParent = {
forType.push({listener: listener,
target: target,
wantsUntrusted: wantsUntrusted,
useCapture: useCapture});
useCapture: useCapture,
delayedWarning: delayedWarning});
},
removeEventListener: function(addon, target, type, listener, useCapture) {
@ -527,8 +529,11 @@ let EventTargetParent = {
// Make a copy in case they call removeEventListener in the listener.
let handlers = [];
for (let {listener, target, wantsUntrusted, useCapture} of forType) {
for (let {listener, target, wantsUntrusted, useCapture, delayedWarning} of forType) {
if ((wantsUntrusted || isTrusted) && useCapture == capturing) {
// Issue a warning for this listener.
delayedWarning();
handlers.push([listener, target]);
}
}
@ -615,10 +620,12 @@ let EventTargetInterposition = new Interposition("EventTargetInterposition");
EventTargetInterposition.methods.addEventListener =
function(addon, target, type, listener, useCapture, wantsUntrusted) {
CompatWarning.warn("Registering an event listener on content DOM nodes" +
" needs to happen in the content process.",
addon, CompatWarning.warnings.DOM_events);
EventTargetParent.addEventListener(addon, target, type, listener, useCapture, wantsUntrusted);
let delayed = CompatWarning.delayedWarning(
"Registering an event listener on content DOM nodes" +
" needs to happen in the content process.",
addon, CompatWarning.warnings.DOM_events);
EventTargetParent.addEventListener(addon, target, type, listener, useCapture, wantsUntrusted, delayed);
target.addEventListener(type, makeFilteringListener(type, listener), useCapture, wantsUntrusted);
};