mirror of
https://github.com/moparisthebest/FireTray
synced 2025-01-08 12:08:05 -05:00
add support for Zotero app
This commit is contained in:
parent
bd83ca9304
commit
1a90dbe179
@ -10,6 +10,7 @@ overlay chrome://songbird/content/xul/mainScriptsOverlay.xul chrome://firetray/c
|
|||||||
overlay chrome://sunbird/content/calendar.xul chrome://firetray/content/overlay.xul
|
overlay chrome://sunbird/content/calendar.xul chrome://firetray/content/overlay.xul
|
||||||
overlay chrome://navigator/content/navigator.xul chrome://firetray/content/overlay.xul
|
overlay chrome://navigator/content/navigator.xul chrome://firetray/content/overlay.xul
|
||||||
overlay chrome://chatzilla/content/chatzilla.xul chrome://firetray/content/overlay.xul
|
overlay chrome://chatzilla/content/chatzilla.xul chrome://firetray/content/overlay.xul
|
||||||
|
overlay chrome://zotero/content/standalone/standalone.xul chrome://firetray/content/overlay.xul
|
||||||
|
|
||||||
component {a9c9cc52-4d6c-45c2-a73f-0be1bd60aaa6} components/firetray-clhandler.js
|
component {a9c9cc52-4d6c-45c2-a73f-0be1bd60aaa6} components/firetray-clhandler.js
|
||||||
contract @mozilla.org/commandlinehandler/general-startup;1?type=firetray {a9c9cc52-4d6c-45c2-a73f-0be1bd60aaa6}
|
contract @mozilla.org/commandlinehandler/general-startup;1?type=firetray {a9c9cc52-4d6c-45c2-a73f-0be1bd60aaa6}
|
||||||
|
1
src/chrome/skin/linux/icons/hicolor/22x22/apps/zotero22.png
Symbolic link
1
src/chrome/skin/linux/icons/hicolor/22x22/apps/zotero22.png
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../zotero22.png
|
BIN
src/chrome/skin/zotero22.png
Normal file
BIN
src/chrome/skin/zotero22.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -47,6 +47,14 @@
|
|||||||
</Description>
|
</Description>
|
||||||
</em:targetApplication>
|
</em:targetApplication>
|
||||||
|
|
||||||
|
<em:targetApplication> <!-- Zotero -->
|
||||||
|
<Description>
|
||||||
|
<em:id>zotero@chnm.gmu.edu</em:id>
|
||||||
|
<em:minVersion>2.1a1</em:minVersion>
|
||||||
|
<em:maxVersion>3.0.*</em:maxVersion>
|
||||||
|
</Description>
|
||||||
|
</em:targetApplication>
|
||||||
|
|
||||||
<em:developer>Jared Forsyth</em:developer>
|
<em:developer>Jared Forsyth</em:developer>
|
||||||
<em:developer>Glen Winters</em:developer>
|
<em:developer>Glen Winters</em:developer>
|
||||||
|
|
||||||
|
@ -472,11 +472,23 @@ firetray.VersionChangeHandler = {
|
|||||||
log.info("appId="+firetray.Handler.appId);
|
log.info("appId="+firetray.Handler.appId);
|
||||||
if (firetray.Handler.appId === FIRETRAY_APP_DB['thunderbird']['id'])
|
if (firetray.Handler.appId === FIRETRAY_APP_DB['thunderbird']['id'])
|
||||||
this.openMailTab(url);
|
this.openMailTab(url);
|
||||||
|
|
||||||
else if (firetray.Handler.appId === FIRETRAY_APP_DB['firefox']['id'] ||
|
else if (firetray.Handler.appId === FIRETRAY_APP_DB['firefox']['id'] ||
|
||||||
firetray.Handler.appId === FIRETRAY_APP_DB['seamonkey']['id'])
|
firetray.Handler.appId === FIRETRAY_APP_DB['seamonkey']['id'])
|
||||||
this.openBrowserTab(url);
|
this.openBrowserTab(url);
|
||||||
else
|
|
||||||
log.error("unsupported application");
|
else if (firetray.Handler.appId === FIRETRAY_APP_DB['zotero']['id']) {
|
||||||
|
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
|
if (!win)
|
||||||
|
log.error("Zotero main-window not found");
|
||||||
|
else
|
||||||
|
win.openDialog("chrome://zotero/content/standalone/basicViewer.xul",
|
||||||
|
"basicViewer",
|
||||||
|
"chrome,resizable,centerscreen,menubar,scrollbars", url);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.openSystemBrowser(url);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
openMailTab: function(url) {
|
openMailTab: function(url) {
|
||||||
@ -514,6 +526,17 @@ firetray.VersionChangeHandler = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
openSystemBrowser: function(url) {
|
||||||
|
try {
|
||||||
|
var uri = Services.io.newURI(url, null, null);
|
||||||
|
var handler = Cc['@mozilla.org/uriloader/external-protocol-service;1']
|
||||||
|
.getService(Ci.nsIExternalProtocolService)
|
||||||
|
.getProtocolHandlerInfo('http');
|
||||||
|
handler.preferredAction = Ci.nsIHandlerInfo.useSystemDefault;
|
||||||
|
handler.launchWithURI(uri, null);
|
||||||
|
} catch (e) {log.error(e);}
|
||||||
|
},
|
||||||
|
|
||||||
tryEraseOldOptions: function() {
|
tryEraseOldOptions: function() {
|
||||||
let v03Options = [
|
let v03Options = [
|
||||||
"close_to_tray", "minimize_to_tray", "start_minimized", "confirm_exit",
|
"close_to_tray", "minimize_to_tray", "start_minimized", "confirm_exit",
|
||||||
|
@ -80,6 +80,11 @@ const FIRETRAY_APP_DB = {
|
|||||||
chatzilla: {
|
chatzilla: {
|
||||||
id: "{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}",
|
id: "{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}",
|
||||||
mainXUL: null
|
mainXUL: null
|
||||||
|
},
|
||||||
|
|
||||||
|
zotero: {
|
||||||
|
id: "zotero@chnm.gmu.edu",
|
||||||
|
mainXUL: null
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -157,21 +157,21 @@ firetray.StatusIcon = {
|
|||||||
let direction = gdkEventScroll.contents.direction;
|
let direction = gdkEventScroll.contents.direction;
|
||||||
switch(direction) {
|
switch(direction) {
|
||||||
case gdk.GDK_SCROLL_UP:
|
case gdk.GDK_SCROLL_UP:
|
||||||
log.debug("SCROLL UP");
|
log.debug("SCROLL UP");
|
||||||
if (scroll_mode === "down_hides")
|
if (scroll_mode === "down_hides")
|
||||||
firetray.Handler.showAllWindows();
|
firetray.Handler.showAllWindows();
|
||||||
else if (scroll_mode === "up_hides")
|
else if (scroll_mode === "up_hides")
|
||||||
firetray.Handler.hideAllWindows();
|
firetray.Handler.hideAllWindows();
|
||||||
break;
|
break;
|
||||||
case gdk.GDK_SCROLL_DOWN:
|
case gdk.GDK_SCROLL_DOWN:
|
||||||
log.debug("SCROLL DOWN");
|
log.debug("SCROLL DOWN");
|
||||||
if (scroll_mode === "down_hides")
|
if (scroll_mode === "down_hides")
|
||||||
firetray.Handler.hideAllWindows();
|
firetray.Handler.hideAllWindows();
|
||||||
else if (scroll_mode === "up_hides")
|
else if (scroll_mode === "up_hides")
|
||||||
firetray.Handler.showAllWindows();
|
firetray.Handler.showAllWindows();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log.error("SCROLL UNKNOWN");
|
log.error("SCROLL UNKNOWN");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
604
src/modules/log4moz.js
Normal file
604
src/modules/log4moz.js
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
this.EXPORTED_SYMBOLS = ['Log4Moz'];
|
||||||
|
|
||||||
|
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
|
||||||
|
|
||||||
|
const ONE_BYTE = 1;
|
||||||
|
const ONE_KILOBYTE = 1024 * ONE_BYTE;
|
||||||
|
const ONE_MEGABYTE = 1024 * ONE_KILOBYTE;
|
||||||
|
|
||||||
|
const STREAM_SEGMENT_SIZE = 4096;
|
||||||
|
const PR_UINT32_MAX = 0xffffffff;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||||
|
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||||
|
|
||||||
|
this.Log4Moz = {
|
||||||
|
Level: {
|
||||||
|
Fatal: 70,
|
||||||
|
Error: 60,
|
||||||
|
Warn: 50,
|
||||||
|
Info: 40,
|
||||||
|
Config: 30,
|
||||||
|
Debug: 20,
|
||||||
|
Trace: 10,
|
||||||
|
All: 0,
|
||||||
|
Desc: {
|
||||||
|
70: "FATAL",
|
||||||
|
60: "ERROR",
|
||||||
|
50: "WARN",
|
||||||
|
40: "INFO",
|
||||||
|
30: "CONFIG",
|
||||||
|
20: "DEBUG",
|
||||||
|
10: "TRACE",
|
||||||
|
0: "ALL"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get repository() {
|
||||||
|
delete Log4Moz.repository;
|
||||||
|
Log4Moz.repository = new LoggerRepository();
|
||||||
|
return Log4Moz.repository;
|
||||||
|
},
|
||||||
|
set repository(value) {
|
||||||
|
delete Log4Moz.repository;
|
||||||
|
Log4Moz.repository = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
LogMessage: LogMessage,
|
||||||
|
Logger: Logger,
|
||||||
|
LoggerRepository: LoggerRepository,
|
||||||
|
|
||||||
|
Formatter: Formatter,
|
||||||
|
BasicFormatter: BasicFormatter,
|
||||||
|
|
||||||
|
Appender: Appender,
|
||||||
|
DumpAppender: DumpAppender,
|
||||||
|
ConsoleAppender: ConsoleAppender,
|
||||||
|
BlockingStreamAppender: BlockingStreamAppender,
|
||||||
|
StorageStreamAppender: StorageStreamAppender,
|
||||||
|
|
||||||
|
// Discouraged due to blocking I/O.
|
||||||
|
FileAppender: FileAppender,
|
||||||
|
RotatingFileAppender: RotatingFileAppender,
|
||||||
|
|
||||||
|
// Logging helper:
|
||||||
|
// let logger = Log4Moz.repository.getLogger("foo");
|
||||||
|
// logger.info(Log4Moz.enumerateInterfaces(someObject).join(","));
|
||||||
|
enumerateInterfaces: function Log4Moz_enumerateInterfaces(aObject) {
|
||||||
|
let interfaces = [];
|
||||||
|
|
||||||
|
for (i in Ci) {
|
||||||
|
try {
|
||||||
|
aObject.QueryInterface(Ci[i]);
|
||||||
|
interfaces.push(i);
|
||||||
|
}
|
||||||
|
catch(ex) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return interfaces;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Logging helper:
|
||||||
|
// let logger = Log4Moz.repository.getLogger("foo");
|
||||||
|
// logger.info(Log4Moz.enumerateProperties(someObject).join(","));
|
||||||
|
enumerateProperties: function Log4Moz_enumerateProps(aObject,
|
||||||
|
aExcludeComplexTypes) {
|
||||||
|
let properties = [];
|
||||||
|
|
||||||
|
for (p in aObject) {
|
||||||
|
try {
|
||||||
|
if (aExcludeComplexTypes &&
|
||||||
|
(typeof aObject[p] == "object" || typeof aObject[p] == "function"))
|
||||||
|
continue;
|
||||||
|
properties.push(p + " = " + aObject[p]);
|
||||||
|
}
|
||||||
|
catch(ex) {
|
||||||
|
properties.push(p + " = " + ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LogMessage
|
||||||
|
* Encapsulates a single log event's data
|
||||||
|
*/
|
||||||
|
function LogMessage(loggerName, level, message){
|
||||||
|
this.loggerName = loggerName;
|
||||||
|
this.message = message;
|
||||||
|
this.level = level;
|
||||||
|
this.time = Date.now();
|
||||||
|
}
|
||||||
|
LogMessage.prototype = {
|
||||||
|
get levelDesc() {
|
||||||
|
if (this.level in Log4Moz.Level.Desc)
|
||||||
|
return Log4Moz.Level.Desc[this.level];
|
||||||
|
return "UNKNOWN";
|
||||||
|
},
|
||||||
|
|
||||||
|
toString: function LogMsg_toString(){
|
||||||
|
return "LogMessage [" + this.time + " " + this.level + " " +
|
||||||
|
this.message + "]";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Logger
|
||||||
|
* Hierarchical version. Logs to all appenders, assigned or inherited
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Logger(name, repository) {
|
||||||
|
if (!repository)
|
||||||
|
repository = Log4Moz.repository;
|
||||||
|
this._name = name;
|
||||||
|
this.children = [];
|
||||||
|
this.ownAppenders = [];
|
||||||
|
this.appenders = [];
|
||||||
|
this._repository = repository;
|
||||||
|
}
|
||||||
|
Logger.prototype = {
|
||||||
|
get name() {
|
||||||
|
return this._name;
|
||||||
|
},
|
||||||
|
|
||||||
|
_level: null,
|
||||||
|
get level() {
|
||||||
|
if (this._level != null)
|
||||||
|
return this._level;
|
||||||
|
if (this.parent)
|
||||||
|
return this.parent.level;
|
||||||
|
dump("log4moz warning: root logger configuration error: no level defined\n");
|
||||||
|
return Log4Moz.Level.All;
|
||||||
|
},
|
||||||
|
set level(level) {
|
||||||
|
this._level = level;
|
||||||
|
},
|
||||||
|
|
||||||
|
_parent: null,
|
||||||
|
get parent() this._parent,
|
||||||
|
set parent(parent) {
|
||||||
|
if (this._parent == parent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Remove ourselves from parent's children
|
||||||
|
if (this._parent) {
|
||||||
|
let index = this._parent.children.indexOf(this);
|
||||||
|
if (index != -1) {
|
||||||
|
this._parent.children.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._parent = parent;
|
||||||
|
parent.children.push(this);
|
||||||
|
this.updateAppenders();
|
||||||
|
},
|
||||||
|
|
||||||
|
updateAppenders: function updateAppenders() {
|
||||||
|
if (this._parent) {
|
||||||
|
let notOwnAppenders = this._parent.appenders.filter(function(appender) {
|
||||||
|
return this.ownAppenders.indexOf(appender) == -1;
|
||||||
|
}, this);
|
||||||
|
this.appenders = notOwnAppenders.concat(this.ownAppenders);
|
||||||
|
} else {
|
||||||
|
this.appenders = this.ownAppenders.slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update children's appenders.
|
||||||
|
for (let i = 0; i < this.children.length; i++) {
|
||||||
|
this.children[i].updateAppenders();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addAppender: function Logger_addAppender(appender) {
|
||||||
|
if (this.ownAppenders.indexOf(appender) != -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.ownAppenders.push(appender);
|
||||||
|
this.updateAppenders();
|
||||||
|
},
|
||||||
|
|
||||||
|
removeAppender: function Logger_removeAppender(appender) {
|
||||||
|
let index = this.ownAppenders.indexOf(appender);
|
||||||
|
if (index == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.ownAppenders.splice(index, 1);
|
||||||
|
this.updateAppenders();
|
||||||
|
},
|
||||||
|
|
||||||
|
log: function Logger_log(level, string) {
|
||||||
|
if (this.level > level)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Hold off on creating the message object until we actually have
|
||||||
|
// an appender that's responsible.
|
||||||
|
let message;
|
||||||
|
let appenders = this.appenders;
|
||||||
|
for (let i = 0; i < appenders.length; i++){
|
||||||
|
let appender = appenders[i];
|
||||||
|
if (appender.level > level)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!message)
|
||||||
|
message = new LogMessage(this._name, level, string);
|
||||||
|
|
||||||
|
appender.append(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fatal: function Logger_fatal(string) {
|
||||||
|
this.log(Log4Moz.Level.Fatal, string);
|
||||||
|
},
|
||||||
|
error: function Logger_error(string) {
|
||||||
|
this.log(Log4Moz.Level.Error, string);
|
||||||
|
},
|
||||||
|
warn: function Logger_warn(string) {
|
||||||
|
this.log(Log4Moz.Level.Warn, string);
|
||||||
|
},
|
||||||
|
info: function Logger_info(string) {
|
||||||
|
this.log(Log4Moz.Level.Info, string);
|
||||||
|
},
|
||||||
|
config: function Logger_config(string) {
|
||||||
|
this.log(Log4Moz.Level.Config, string);
|
||||||
|
},
|
||||||
|
debug: function Logger_debug(string) {
|
||||||
|
this.log(Log4Moz.Level.Debug, string);
|
||||||
|
},
|
||||||
|
trace: function Logger_trace(string) {
|
||||||
|
this.log(Log4Moz.Level.Trace, string);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LoggerRepository
|
||||||
|
* Implements a hierarchy of Loggers
|
||||||
|
*/
|
||||||
|
|
||||||
|
function LoggerRepository() {}
|
||||||
|
LoggerRepository.prototype = {
|
||||||
|
_loggers: {},
|
||||||
|
|
||||||
|
_rootLogger: null,
|
||||||
|
get rootLogger() {
|
||||||
|
if (!this._rootLogger) {
|
||||||
|
this._rootLogger = new Logger("root", this);
|
||||||
|
this._rootLogger.level = Log4Moz.Level.All;
|
||||||
|
}
|
||||||
|
return this._rootLogger;
|
||||||
|
},
|
||||||
|
set rootLogger(logger) {
|
||||||
|
throw "Cannot change the root logger";
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateParents: function LogRep__updateParents(name) {
|
||||||
|
let pieces = name.split('.');
|
||||||
|
let cur, parent;
|
||||||
|
|
||||||
|
// find the closest parent
|
||||||
|
// don't test for the logger name itself, as there's a chance it's already
|
||||||
|
// there in this._loggers
|
||||||
|
for (let i = 0; i < pieces.length - 1; i++) {
|
||||||
|
if (cur)
|
||||||
|
cur += '.' + pieces[i];
|
||||||
|
else
|
||||||
|
cur = pieces[i];
|
||||||
|
if (cur in this._loggers)
|
||||||
|
parent = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we didn't assign a parent above, there is no parent
|
||||||
|
if (!parent)
|
||||||
|
this._loggers[name].parent = this.rootLogger;
|
||||||
|
else
|
||||||
|
this._loggers[name].parent = this._loggers[parent];
|
||||||
|
|
||||||
|
// trigger updates for any possible descendants of this logger
|
||||||
|
for (let logger in this._loggers) {
|
||||||
|
if (logger != name && logger.indexOf(name) == 0)
|
||||||
|
this._updateParents(logger);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getLogger: function LogRep_getLogger(name) {
|
||||||
|
if (name in this._loggers)
|
||||||
|
return this._loggers[name];
|
||||||
|
this._loggers[name] = new Logger(name, this);
|
||||||
|
this._updateParents(name);
|
||||||
|
return this._loggers[name];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Formatters
|
||||||
|
* These massage a LogMessage into whatever output is desired
|
||||||
|
* Only the BasicFormatter is currently implemented
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Abstract formatter
|
||||||
|
function Formatter() {}
|
||||||
|
Formatter.prototype = {
|
||||||
|
format: function Formatter_format(message) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Basic formatter that doesn't do anything fancy
|
||||||
|
function BasicFormatter(dateFormat) {
|
||||||
|
if (dateFormat)
|
||||||
|
this.dateFormat = dateFormat;
|
||||||
|
}
|
||||||
|
BasicFormatter.prototype = {
|
||||||
|
__proto__: Formatter.prototype,
|
||||||
|
|
||||||
|
format: function BF_format(message) {
|
||||||
|
return message.time + "\t" + message.loggerName + "\t" + message.levelDesc
|
||||||
|
+ "\t" + message.message + "\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appenders
|
||||||
|
* These can be attached to Loggers to log to different places
|
||||||
|
* Simply subclass and override doAppend to implement a new one
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Appender(formatter) {
|
||||||
|
this._name = "Appender";
|
||||||
|
this._formatter = formatter? formatter : new BasicFormatter();
|
||||||
|
}
|
||||||
|
Appender.prototype = {
|
||||||
|
level: Log4Moz.Level.All,
|
||||||
|
|
||||||
|
append: function App_append(message) {
|
||||||
|
this.doAppend(this._formatter.format(message));
|
||||||
|
},
|
||||||
|
toString: function App_toString() {
|
||||||
|
return this._name + " [level=" + this._level +
|
||||||
|
", formatter=" + this._formatter + "]";
|
||||||
|
},
|
||||||
|
doAppend: function App_doAppend(message) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DumpAppender
|
||||||
|
* Logs to standard out
|
||||||
|
*/
|
||||||
|
|
||||||
|
function DumpAppender(formatter) {
|
||||||
|
this._name = "DumpAppender";
|
||||||
|
Appender.call(this, formatter);
|
||||||
|
}
|
||||||
|
DumpAppender.prototype = {
|
||||||
|
__proto__: Appender.prototype,
|
||||||
|
|
||||||
|
doAppend: function DApp_doAppend(message) {
|
||||||
|
dump(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ConsoleAppender
|
||||||
|
* Logs to the javascript console
|
||||||
|
*/
|
||||||
|
|
||||||
|
function ConsoleAppender(formatter) {
|
||||||
|
this._name = "ConsoleAppender";
|
||||||
|
Appender.call(this, formatter);
|
||||||
|
}
|
||||||
|
ConsoleAppender.prototype = {
|
||||||
|
__proto__: Appender.prototype,
|
||||||
|
|
||||||
|
doAppend: function CApp_doAppend(message) {
|
||||||
|
if (message.level > Log4Moz.Level.Warn) {
|
||||||
|
Cu.reportError(message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Cc["@mozilla.org/consoleservice;1"].
|
||||||
|
getService(Ci.nsIConsoleService).logStringMessage(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base implementation for stream based appenders.
|
||||||
|
*
|
||||||
|
* Caution: This writes to the output stream synchronously, thus logging calls
|
||||||
|
* block as the data is written to the stream. This can have negligible impact
|
||||||
|
* for in-memory streams, but should be taken into account for I/O streams
|
||||||
|
* (files, network, etc.)
|
||||||
|
*/
|
||||||
|
function BlockingStreamAppender(formatter) {
|
||||||
|
this._name = "BlockingStreamAppender";
|
||||||
|
Appender.call(this, formatter);
|
||||||
|
}
|
||||||
|
BlockingStreamAppender.prototype = {
|
||||||
|
__proto__: Appender.prototype,
|
||||||
|
|
||||||
|
_converterStream: null, // holds the nsIConverterOutputStream
|
||||||
|
_outputStream: null, // holds the underlying nsIOutputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output stream to write to.
|
||||||
|
*
|
||||||
|
* This will automatically open the stream if it doesn't exist yet by
|
||||||
|
* calling newOutputStream. The resulting raw stream is wrapped in a
|
||||||
|
* nsIConverterOutputStream to ensure text is written as UTF-8.
|
||||||
|
*/
|
||||||
|
get outputStream() {
|
||||||
|
if (!this._outputStream) {
|
||||||
|
// First create a raw stream. We can bail out early if that fails.
|
||||||
|
this._outputStream = this.newOutputStream();
|
||||||
|
if (!this._outputStream) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap the raw stream in an nsIConverterOutputStream. We can reuse
|
||||||
|
// the instance if we already have one.
|
||||||
|
if (!this._converterStream) {
|
||||||
|
this._converterStream = Cc["@mozilla.org/intl/converter-output-stream;1"]
|
||||||
|
.createInstance(Ci.nsIConverterOutputStream);
|
||||||
|
}
|
||||||
|
this._converterStream.init(
|
||||||
|
this._outputStream, "UTF-8", STREAM_SEGMENT_SIZE,
|
||||||
|
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
||||||
|
}
|
||||||
|
return this._converterStream;
|
||||||
|
},
|
||||||
|
|
||||||
|
newOutputStream: function newOutputStream() {
|
||||||
|
throw "Stream-based appenders need to implement newOutputStream()!";
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function reset() {
|
||||||
|
if (!this._outputStream) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.outputStream.close();
|
||||||
|
this._outputStream = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
doAppend: function doAppend(message) {
|
||||||
|
if (!message) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.outputStream.writeString(message);
|
||||||
|
} catch(ex) {
|
||||||
|
if (ex.result == Cr.NS_BASE_STREAM_CLOSED) {
|
||||||
|
// The underlying output stream is closed, so let's open a new one
|
||||||
|
// and try again.
|
||||||
|
this._outputStream = null;
|
||||||
|
try {
|
||||||
|
this.outputStream.writeString(message);
|
||||||
|
} catch (ex) {
|
||||||
|
// Ah well, we tried, but something seems to be hosed permanently.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append to an nsIStorageStream
|
||||||
|
*
|
||||||
|
* This writes logging output to an in-memory stream which can later be read
|
||||||
|
* back as an nsIInputStream. It can be used to avoid expensive I/O operations
|
||||||
|
* during logging. Instead, one can periodically consume the input stream and
|
||||||
|
* e.g. write it to disk asynchronously.
|
||||||
|
*/
|
||||||
|
function StorageStreamAppender(formatter) {
|
||||||
|
this._name = "StorageStreamAppender";
|
||||||
|
BlockingStreamAppender.call(this, formatter);
|
||||||
|
}
|
||||||
|
StorageStreamAppender.prototype = {
|
||||||
|
__proto__: BlockingStreamAppender.prototype,
|
||||||
|
|
||||||
|
_ss: null,
|
||||||
|
newOutputStream: function newOutputStream() {
|
||||||
|
let ss = this._ss = Cc["@mozilla.org/storagestream;1"]
|
||||||
|
.createInstance(Ci.nsIStorageStream);
|
||||||
|
ss.init(STREAM_SEGMENT_SIZE, PR_UINT32_MAX, null);
|
||||||
|
return ss.getOutputStream(0);
|
||||||
|
},
|
||||||
|
|
||||||
|
getInputStream: function getInputStream() {
|
||||||
|
if (!this._ss) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this._ss.newInputStream(0);
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function reset() {
|
||||||
|
BlockingStreamAppender.prototype.reset.call(this);
|
||||||
|
this._ss = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File appender (discouraged)
|
||||||
|
*
|
||||||
|
* Writes otuput to a file using a regular nsIFileOutputStream (as opposed
|
||||||
|
* to nsISafeFileOutputStream, since immediate durability is typically not
|
||||||
|
* needed for logs.) Note that I/O operations block the logging caller.
|
||||||
|
*/
|
||||||
|
function FileAppender(file, formatter) {
|
||||||
|
this._name = "FileAppender";
|
||||||
|
this._file = file; // nsIFile
|
||||||
|
BlockingStreamAppender.call(this, formatter);
|
||||||
|
}
|
||||||
|
FileAppender.prototype = {
|
||||||
|
__proto__: BlockingStreamAppender.prototype,
|
||||||
|
|
||||||
|
newOutputStream: function newOutputStream() {
|
||||||
|
try {
|
||||||
|
return FileUtils.openFileOutputStream(this._file);
|
||||||
|
} catch(e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function reset() {
|
||||||
|
BlockingStreamAppender.prototype.reset.call(this);
|
||||||
|
try {
|
||||||
|
this._file.remove(false);
|
||||||
|
} catch (e) {
|
||||||
|
// File didn't exist in the first place, or we're on Windows. Meh.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotating file appender (discouraged)
|
||||||
|
*
|
||||||
|
* Similar to FileAppender, but rotates logs when they become too large.
|
||||||
|
*/
|
||||||
|
function RotatingFileAppender(file, formatter, maxSize, maxBackups) {
|
||||||
|
if (maxSize === undefined)
|
||||||
|
maxSize = ONE_MEGABYTE * 2;
|
||||||
|
|
||||||
|
if (maxBackups === undefined)
|
||||||
|
maxBackups = 0;
|
||||||
|
|
||||||
|
this._name = "RotatingFileAppender";
|
||||||
|
FileAppender.call(this, file, formatter);
|
||||||
|
this._maxSize = maxSize;
|
||||||
|
this._maxBackups = maxBackups;
|
||||||
|
}
|
||||||
|
RotatingFileAppender.prototype = {
|
||||||
|
__proto__: FileAppender.prototype,
|
||||||
|
|
||||||
|
doAppend: function doAppend(message) {
|
||||||
|
FileAppender.prototype.doAppend.call(this, message);
|
||||||
|
try {
|
||||||
|
this.rotateLogs();
|
||||||
|
} catch(e) {
|
||||||
|
dump("Error writing file:" + e + "\n");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
rotateLogs: function rotateLogs() {
|
||||||
|
if (this._file.exists() && this._file.fileSize < this._maxSize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockingStreamAppender.prototype.reset.call(this);
|
||||||
|
|
||||||
|
for (let i = this.maxBackups - 1; i > 0; i--) {
|
||||||
|
let backup = this._file.parent.clone();
|
||||||
|
backup.append(this._file.leafName + "." + i);
|
||||||
|
if (backup.exists()) {
|
||||||
|
backup.moveTo(this._file.parent, this._file.leafName + "." + (i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cur = this._file.clone();
|
||||||
|
if (cur.exists()) {
|
||||||
|
cur.moveTo(cur.parent, cur.leafName + ".1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this._file still points to the same file
|
||||||
|
}
|
||||||
|
};
|
@ -54,7 +54,8 @@ firetray.Logging = {
|
|||||||
if (this.initialized) return;
|
if (this.initialized) return;
|
||||||
|
|
||||||
["resource://services-common/log4moz.js", // FF
|
["resource://services-common/log4moz.js", // FF
|
||||||
"resource:///modules/gloda/log4moz.js"] // TB
|
"resource:///modules/gloda/log4moz.js", // TB
|
||||||
|
"resource://firetray/log4moz.js"] // default
|
||||||
.forEach(function(file){
|
.forEach(function(file){
|
||||||
try {Cu.import(file);} catch(x) {}
|
try {Cu.import(file);} catch(x) {}
|
||||||
}, this);
|
}, this);
|
||||||
|
Loading…
Reference in New Issue
Block a user