Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 const Cc = Components.classes;
8 const Ci = Components.interfaces;
9 const Cr = Components.results;
11 const KEY_PROFILEDIR = "ProfD";
12 const FILE_EXTENSIONS_LOG = "extensions.log";
13 const PREF_LOGGING_ENABLED = "extensions.logging.enabled";
15 const LOGGER_FILE_PERM = parseInt("666", 8);
17 const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
19 Components.utils.import("resource://gre/modules/FileUtils.jsm");
20 Components.utils.import("resource://gre/modules/Services.jsm");
22 this.EXPORTED_SYMBOLS = [ "LogManager" ];
24 var gDebugLogEnabled = false;
26 function formatLogMessage(aType, aName, aStr, aException) {
27 let message = aType.toUpperCase() + " " + aName + ": " + aStr;
28 if (aException) {
29 if (typeof aException == "number")
30 return message + ": " + Components.Exception("", aException).name;
32 message = message + ": " + aException;
33 // instanceOf doesn't work here, let's duck type
34 if (aException.fileName)
35 message = message + " (" + aException.fileName + ":" + aException.lineNumber + ")";
37 if (aException.message == "too much recursion")
38 dump(message + "\n" + aException.stack + "\n");
39 }
40 return message;
41 }
43 function getStackDetails(aException) {
44 // Defensively wrap all this to ensure that failing to get the message source
45 // doesn't stop the message from being logged
46 try {
47 if (aException) {
48 if (aException instanceof Ci.nsIException) {
49 return {
50 sourceName: aException.filename,
51 lineNumber: aException.lineNumber
52 };
53 }
55 if (typeof aException == "object") {
56 return {
57 sourceName: aException.fileName,
58 lineNumber: aException.lineNumber
59 };
60 }
61 }
63 let stackFrame = Components.stack.caller.caller.caller;
64 return {
65 sourceName: stackFrame.filename,
66 lineNumber: stackFrame.lineNumber
67 };
68 }
69 catch (e) {
70 return {
71 sourceName: null,
72 lineNumber: 0
73 };
74 }
75 }
77 function AddonLogger(aName) {
78 this.name = aName;
79 }
81 AddonLogger.prototype = {
82 name: null,
84 error: function AddonLogger_error(aStr, aException) {
85 let message = formatLogMessage("error", this.name, aStr, aException);
87 let stack = getStackDetails(aException);
89 let consoleMessage = Cc["@mozilla.org/scripterror;1"].
90 createInstance(Ci.nsIScriptError);
91 consoleMessage.init(message, stack.sourceName, null, stack.lineNumber, 0,
92 Ci.nsIScriptError.errorFlag, "component javascript");
93 Services.console.logMessage(consoleMessage);
95 // Always dump errors, in case the Console Service isn't listening yet
96 dump("*** " + message + "\n");
98 try {
99 var tstamp = new Date();
100 var logfile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_EXTENSIONS_LOG]);
101 var stream = Cc["@mozilla.org/network/file-output-stream;1"].
102 createInstance(Ci.nsIFileOutputStream);
103 stream.init(logfile, 0x02 | 0x08 | 0x10, LOGGER_FILE_PERM, 0); // write, create, append
104 var writer = Cc["@mozilla.org/intl/converter-output-stream;1"].
105 createInstance(Ci.nsIConverterOutputStream);
106 writer.init(stream, "UTF-8", 0, 0x0000);
107 writer.writeString(tstamp.toLocaleFormat("%Y-%m-%d %H:%M:%S ") +
108 message + " at " + stack.sourceName + ":" +
109 stack.lineNumber + "\n");
110 writer.close();
111 }
112 catch (e) { }
113 },
115 warn: function AddonLogger_warn(aStr, aException) {
116 let message = formatLogMessage("warn", this.name, aStr, aException);
118 let stack = getStackDetails(aException);
120 let consoleMessage = Cc["@mozilla.org/scripterror;1"].
121 createInstance(Ci.nsIScriptError);
122 consoleMessage.init(message, stack.sourceName, null, stack.lineNumber, 0,
123 Ci.nsIScriptError.warningFlag, "component javascript");
124 Services.console.logMessage(consoleMessage);
126 if (gDebugLogEnabled)
127 dump("*** " + message + "\n");
128 },
130 log: function AddonLogger_log(aStr, aException) {
131 if (gDebugLogEnabled) {
132 let message = formatLogMessage("log", this.name, aStr, aException);
133 dump("*** " + message + "\n");
134 Services.console.logStringMessage(message);
135 }
136 }
137 };
139 this.LogManager = {
140 getLogger: function LogManager_getLogger(aName, aTarget) {
141 let logger = new AddonLogger(aName);
143 if (aTarget) {
144 ["error", "warn", "log"].forEach(function(name) {
145 let fname = name.toUpperCase();
146 delete aTarget[fname];
147 aTarget[fname] = function LogManager_targetName(aStr, aException) {
148 logger[name](aStr, aException);
149 };
150 });
151 }
153 return logger;
154 }
155 };
157 var PrefObserver = {
158 init: function PrefObserver_init() {
159 Services.prefs.addObserver(PREF_LOGGING_ENABLED, this, false);
160 Services.obs.addObserver(this, "xpcom-shutdown", false);
161 this.observe(null, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, PREF_LOGGING_ENABLED);
162 },
164 observe: function PrefObserver_observe(aSubject, aTopic, aData) {
165 if (aTopic == "xpcom-shutdown") {
166 Services.prefs.removeObserver(PREF_LOGGING_ENABLED, this);
167 Services.obs.removeObserver(this, "xpcom-shutdown");
168 }
169 else if (aTopic == NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) {
170 try {
171 gDebugLogEnabled = Services.prefs.getBoolPref(PREF_LOGGING_ENABLED);
172 }
173 catch (e) {
174 gDebugLogEnabled = false;
175 }
176 }
177 }
178 };
180 PrefObserver.init();