diff options
author | Matt A. Tobin <email@mattatobin.com> | 2018-02-11 07:03:16 -0500 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2018-02-11 07:03:16 -0500 |
commit | 203eb0f61a09372310a2a8fb57e169cb3f47800b (patch) | |
tree | 8490329d3dae4de3c7ffd127bce1f65fdc009abd /toolkit/mozapps/extensions/internal/AddonLogging.jsm | |
parent | e45706ca3acbb6530419433212becc61d5953a2d (diff) | |
parent | 8f6d3dab81c7f8f97ef197e26ab9439b09735b8f (diff) | |
download | UXP-203eb0f61a09372310a2a8fb57e169cb3f47800b.tar UXP-203eb0f61a09372310a2a8fb57e169cb3f47800b.tar.gz UXP-203eb0f61a09372310a2a8fb57e169cb3f47800b.tar.lz UXP-203eb0f61a09372310a2a8fb57e169cb3f47800b.tar.xz UXP-203eb0f61a09372310a2a8fb57e169cb3f47800b.zip |
Merge branch 'ext-work'FF_Checkpoint_1
Diffstat (limited to 'toolkit/mozapps/extensions/internal/AddonLogging.jsm')
-rw-r--r-- | toolkit/mozapps/extensions/internal/AddonLogging.jsm | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/toolkit/mozapps/extensions/internal/AddonLogging.jsm b/toolkit/mozapps/extensions/internal/AddonLogging.jsm new file mode 100644 index 000000000..362439bae --- /dev/null +++ b/toolkit/mozapps/extensions/internal/AddonLogging.jsm @@ -0,0 +1,180 @@ +/* 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"; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; + +const KEY_PROFILEDIR = "ProfD"; +const FILE_EXTENSIONS_LOG = "extensions.log"; +const PREF_LOGGING_ENABLED = "extensions.logging.enabled"; + +const LOGGER_FILE_PERM = parseInt("666", 8); + +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; + +Components.utils.import("resource://gre/modules/FileUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +this.EXPORTED_SYMBOLS = [ "LogManager" ]; + +var gDebugLogEnabled = false; + +function formatLogMessage(aType, aName, aStr, aException) { + let message = aType.toUpperCase() + " " + aName + ": " + aStr; + if (aException) { + if (typeof aException == "number") + return message + ": " + Components.Exception("", aException).name; + + message = message + ": " + aException; + // instanceOf doesn't work here, let's duck type + if (aException.fileName) + message = message + " (" + aException.fileName + ":" + aException.lineNumber + ")"; + + if (aException.message == "too much recursion") + dump(message + "\n" + aException.stack + "\n"); + } + return message; +} + +function getStackDetails(aException) { + // Defensively wrap all this to ensure that failing to get the message source + // doesn't stop the message from being logged + try { + if (aException) { + if (aException instanceof Ci.nsIException) { + return { + sourceName: aException.filename, + lineNumber: aException.lineNumber + }; + } + + if (typeof aException == "object") { + return { + sourceName: aException.fileName, + lineNumber: aException.lineNumber + }; + } + } + + let stackFrame = Components.stack.caller.caller.caller; + return { + sourceName: stackFrame.filename, + lineNumber: stackFrame.lineNumber + }; + } + catch (e) { + return { + sourceName: null, + lineNumber: 0 + }; + } +} + +function AddonLogger(aName) { + this.name = aName; +} + +AddonLogger.prototype = { + name: null, + + error: function AddonLogger_error(aStr, aException) { + let message = formatLogMessage("error", this.name, aStr, aException); + + let stack = getStackDetails(aException); + + let consoleMessage = Cc["@mozilla.org/scripterror;1"]. + createInstance(Ci.nsIScriptError); + consoleMessage.init(message, stack.sourceName, null, stack.lineNumber, 0, + Ci.nsIScriptError.errorFlag, "component javascript"); + Services.console.logMessage(consoleMessage); + + // Always dump errors, in case the Console Service isn't listening yet + dump("*** " + message + "\n"); + + try { + var tstamp = new Date(); + var logfile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_EXTENSIONS_LOG]); + var stream = Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(Ci.nsIFileOutputStream); + stream.init(logfile, 0x02 | 0x08 | 0x10, LOGGER_FILE_PERM, 0); // write, create, append + var writer = Cc["@mozilla.org/intl/converter-output-stream;1"]. + createInstance(Ci.nsIConverterOutputStream); + writer.init(stream, "UTF-8", 0, 0x0000); + writer.writeString(tstamp.toLocaleFormat("%Y-%m-%d %H:%M:%S ") + + message + " at " + stack.sourceName + ":" + + stack.lineNumber + "\n"); + writer.close(); + } + catch (e) { } + }, + + warn: function AddonLogger_warn(aStr, aException) { + let message = formatLogMessage("warn", this.name, aStr, aException); + + let stack = getStackDetails(aException); + + let consoleMessage = Cc["@mozilla.org/scripterror;1"]. + createInstance(Ci.nsIScriptError); + consoleMessage.init(message, stack.sourceName, null, stack.lineNumber, 0, + Ci.nsIScriptError.warningFlag, "component javascript"); + Services.console.logMessage(consoleMessage); + + if (gDebugLogEnabled) + dump("*** " + message + "\n"); + }, + + log: function AddonLogger_log(aStr, aException) { + if (gDebugLogEnabled) { + let message = formatLogMessage("log", this.name, aStr, aException); + dump("*** " + message + "\n"); + Services.console.logStringMessage(message); + } + } +}; + +this.LogManager = { + getLogger: function LogManager_getLogger(aName, aTarget) { + let logger = new AddonLogger(aName); + + if (aTarget) { + ["error", "warn", "log"].forEach(function(name) { + let fname = name.toUpperCase(); + delete aTarget[fname]; + aTarget[fname] = function LogManager_targetName(aStr, aException) { + logger[name](aStr, aException); + }; + }); + } + + return logger; + } +}; + +var PrefObserver = { + init: function PrefObserver_init() { + Services.prefs.addObserver(PREF_LOGGING_ENABLED, this, false); + Services.obs.addObserver(this, "xpcom-shutdown", false); + this.observe(null, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, PREF_LOGGING_ENABLED); + }, + + observe: function PrefObserver_observe(aSubject, aTopic, aData) { + if (aTopic == "xpcom-shutdown") { + Services.prefs.removeObserver(PREF_LOGGING_ENABLED, this); + Services.obs.removeObserver(this, "xpcom-shutdown"); + } + else if (aTopic == NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) { + try { + gDebugLogEnabled = Services.prefs.getBoolPref(PREF_LOGGING_ENABLED); + } + catch (e) { + gDebugLogEnabled = false; + } + } + } +}; + +PrefObserver.init(); |