Bug 553112: Add a shared module for add-ons manager logging. g. r=robstrong
authorDave Townsend <dtownsend@oxymoronical.com>
Mon, 26 Apr 2010 12:12:46 -0700
changeset 41247 c7fd38eaf53c148700bb3a60b4ebf6993833690c
parent 41246 f7b419efa248a3ab7d50a19e49aab4953a9f7af1
child 41248 74b9ef86dc842217c531ab4c6052461d0ab6a0dc
push id141
push userdtownsend@mozilla.com
push dateMon, 26 Apr 2010 19:12:58 +0000
reviewersrobstrong
bugs553112
milestone1.9.3a5pre
Bug 553112: Add a shared module for add-ons manager logging. g. r=robstrong
toolkit/mozapps/extensions/AddonLogging.jsm
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/AddonUpdateChecker.jsm
toolkit/mozapps/extensions/Makefile.in
toolkit/mozapps/extensions/PluginProvider.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/amWebInstallListener.js
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/AddonLogging.jsm
@@ -0,0 +1,137 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Extension Manager.
+#
+# The Initial Developer of the Original Code is
+# the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Dave Townsend <dtownsend@oxymoronical.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+const KEY_PROFILEDIR                  = "ProfD";
+const FILE_EXTENSIONS_LOG             = "extensions.log";
+
+Components.utils.import("resource://gre/modules/FileUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+var EXPORTED_SYMBOLS = [ "LogManager" ];
+
+var gDebugLogEnabled = false;
+
+function formatLogMessage(aType, aName, aStr) {
+  return aType.toUpperCase() + " " + aName + ": " + aStr;
+}
+
+function AddonLogger(aName) {
+  this.name = aName;
+}
+
+AddonLogger.prototype = {
+  name: null,
+
+  error: function(aStr) {
+    let message = formatLogMessage("error", this.name, aStr);
+
+    let consoleMessage = Cc["@mozilla.org/scripterror;1"].
+                         createInstance(Ci.nsIScriptError);
+    consoleMessage.init(message, null, null, 0, 0, Ci.nsIScriptError.errorFlag,
+                        "component javascript");
+    Services.console.logMessage(consoleMessage);
+
+    if (gDebugLogEnabled)
+      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, 0666, 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 + "\n");
+      writer.close();
+    }
+    catch (e) { }
+  },
+
+  warn: function(aStr) {
+    let message = formatLogMessage("warn", this.name, aStr);
+
+    let consoleMessage = Cc["@mozilla.org/scripterror;1"].
+                         createInstance(Ci.nsIScriptError);
+    consoleMessage.init(message, null, null, 0, 0, Ci.nsIScriptError.warningFlag,
+                        "component javascript");
+    Services.console.logMessage(consoleMessage);
+
+    if (gDebugLogEnabled)
+      dump("*** " + message + "\n");
+  },
+
+  log: function(aStr) {
+    if (gDebugLogEnabled) {
+      let message = formatLogMessage("log", this.name, aStr);
+      dump("*** " + message + "\n");
+      Services.console.logStringMessage(message);
+    }
+  }
+};
+
+var LogManager = {
+  getLogger: function(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(aStr) {
+          logger[name](aStr);
+        };
+      });
+    }
+
+    return logger;
+  }
+};
+
+try {
+  gDebugLogEnabled = Services.prefs.getBoolPref("extensions.logging.enabled");
+}
+catch (e) {
+}
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -49,45 +49,24 @@ var EXPORTED_SYMBOLS = [ "AddonManager",
 
 // A list of providers to load by default
 const PROVIDERS = [
   "resource://gre/modules/XPIProvider.jsm",
   "resource://gre/modules/PluginProvider.jsm",
   "resource://gre/modules/LightweightThemeManager.jsm"
 ];
 
-/**
- * Logs a debugging message.
- *
- * @param  aStr
- *         The string to log
- */
-function LOG(aStr) {
-  dump("*** addons.manager: " + aStr + "\n");
-}
+["LOG", "WARN", "ERROR"].forEach(function(aName) {
+  this.__defineGetter__(aName, function() {
+    Components.utils.import("resource://gre/modules/AddonLogging.jsm");
 
-/**
- * Logs a warning message.
- *
- * @param  aStr
- *         The string to log
- */
-function WARN(aStr) {
-  LOG(aStr);
-}
-
-/**
- * Logs an error message.
- *
- * @param  aStr
- *         The string to log
- */
-function ERROR(aStr) {
-  LOG(aStr);
-}
+    LogManager.getLogger("addons.manager", this);
+    return this[aName];
+  });
+}, this);
 
 /**
  * Calls a callback method consuming any thrown exception. Any parameters after
  * the callback parameter will be passed to the callback.
  *
  * @param  aCallback
  *         The callback method to call
  */
--- a/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
+++ b/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
@@ -58,45 +58,24 @@ const XMLURI_PARSE_ERROR    = "http://ww
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 // shared code for suppressing bad cert dialogs
 Components.utils.import("resource://gre/modules/CertUtils.jsm");
 
 var gRDF = Cc["@mozilla.org/rdf/rdf-service;1"].
            getService(Ci.nsIRDFService);
 
-/**
- * Logs a debug message.
- *
- * @param  aStr
- *         The string to log
- */
-function LOG(aStr) {
-  dump("*** addons.updates: " + aStr + "\n");
-}
+["LOG", "WARN", "ERROR"].forEach(function(aName) {
+  this.__defineGetter__(aName, function() {
+    Components.utils.import("resource://gre/modules/AddonLogging.jsm");
 
-/**
- * Logs a warning message
- *
- * @param  aStr
- *         The string to log
- */
-function WARN(aStr) {
-  LOG(aStr);
-}
-
-/**
- * Logs an error message
- *
- * @param  aStr
- *         The string to log
- */
-function ERROR(aStr) {
-  LOG(str);
-}
+    LogManager.getLogger("addons.updates", this);
+    return this[aName];
+  });
+}, this);
 
 /**
  * A serialisation method for RDF data that produces an identical string
  * for matching RDF graphs.
  * The serialisation is not complete, only assertions stemming from a given
  * resource are included, multiple references to the same resource are not
  * permitted, and the RDF prolog and epilog are not included.
  * RDF Blob and Date literals are not supported.
--- a/toolkit/mozapps/extensions/Makefile.in
+++ b/toolkit/mozapps/extensions/Makefile.in
@@ -68,16 +68,17 @@ EXTRA_PP_COMPONENTS = \
   amWebInstallListener.js \
   $(NULL)
 
 EXTRA_PP_JS_MODULES = \
   AddonManager.jsm \
   XPIProvider.jsm \
   PluginProvider.jsm \
   AddonUpdateChecker.jsm \
+  AddonLogging.jsm \
   $(NULL)
 
 EXTRA_JS_MODULES = \
   LightweightThemeManager.jsm \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += test
--- a/toolkit/mozapps/extensions/PluginProvider.jsm
+++ b/toolkit/mozapps/extensions/PluginProvider.jsm
@@ -40,45 +40,24 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 var EXPORTED_SYMBOLS = [];
 
 Components.utils.import("resource://gre/modules/AddonManager.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
-/**
- * Logs a debug message.
- *
- * @param  aStr
- *         The string to log
- */
-function LOG(aStr) {
-  dump("*** addons.plugins: " + aStr + "\n");
-}
+["LOG", "WARN", "ERROR"].forEach(function(aName) {
+  this.__defineGetter__(aName, function() {
+    Components.utils.import("resource://gre/modules/AddonLogging.jsm");
 
-/**
- * Logs a warning message.
- *
- * @param  aStr
- *         The string to log
- */
-function WARN(aStr) {
-  LOG(aStr);
-}
-
-/**
- * Logs an error message.
- *
- * @param  aStr
- *         The string to log
- */
-function ERROR(aStr) {
-  LOG(aStr);
-}
+    LogManager.getLogger("addons.plugins", this);
+    return this[aName];
+  });
+}, this);
 
 var PluginProvider = {
   // A dictionary mapping IDs to names and descriptions
   plugins: null,
 
   /**
    * Called to get an Addon with a particular ID.
    *
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -125,45 +125,24 @@ const TYPES = {
   locale: 8
 };
 
 /**
  * Valid IDs fit this pattern.
  */
 var gIDTest = /^(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)$/i;
 
-/**
- * Logs a debug message.
- *
- * @param  aStr
- *         The string to log
- */
-function LOG(aStr) {
-  dump("*** addons.xpi: " + aStr + "\n");
-}
-
-/**
- * Logs a warning message.
- *
- * @param  str
- *         The string to log
- */
-function WARN(aStr) {
-  LOG(aStr);
-}
-
-/**
- * Logs an error message.
- *
- * @param  str
- *         The string to log
- */
-function ERROR(aStr) {
-  LOG(aStr);
-}
+["LOG", "WARN", "ERROR"].forEach(function(aName) {
+  this.__defineGetter__(aName, function() {
+    Components.utils.import("resource://gre/modules/AddonLogging.jsm");
+
+    LogManager.getLogger("addons.xpi", this);
+    return this[aName];
+  })
+}, this);
 
 /**
  * Gets the currently selected locale for display.
  * @return  the selected locale or "en-US" if none is selected
  */
 function getLocale() {
   if (Prefs.getBoolPref(PREF_MATCH_OS_LOCALE), false)
     return Services.locale.getLocaleComponentForUserAgent();
--- a/toolkit/mozapps/extensions/amWebInstallListener.js
+++ b/toolkit/mozapps/extensions/amWebInstallListener.js
@@ -47,25 +47,24 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/AddonManager.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
-/**
- * Logs a warning message
- *
- * @param  aStr
- *         The string to log
- */
-function WARN(aStr) {
-  dump("*** addons.weblistener: " + aStr + "\n");
-}
+["LOG", "WARN", "ERROR"].forEach(function(aName) {
+  this.__defineGetter__(aName, function() {
+    Components.utils.import("resource://gre/modules/AddonLogging.jsm");
+
+    LogManager.getLogger("addons.weblistener", this);
+    return this[aName];
+  });
+}, this);
 
 /**
  * Creates a new installer to monitor downloads and prompt to install when
  * ready
  *
  * @param  aWindow
  *         The window that started the installations
  * @param  aUrl
@@ -185,17 +184,16 @@ extWebInstallListener.prototype = {
    */
   onWebInstallBlocked: function(aWindow, aUri, aInstalls) {
     let info = {
       originatingWindow: aWindow,
       originatingURI: aUri,
       installs: aInstalls,
 
       install: function() {
-        dump("Start installs\n");
         new Installer(this.originatingWindow, this.originatingURI, this.installs);
       },
 
       QueryInterface: XPCOMUtils.generateQI([Ci.amIWebInstallInfo])
     };
     Services.obs.notifyObservers(info, "addon-install-blocked", null);
 
     return false;