Bug 955260 - Add an easy way to copy an account specific debug log, r=clokep.

This commit is contained in:
Florian Quèze 2012-11-28 01:18:38 +01:00
Родитель 18d7cecf1d
Коммит f32a234cf6
13 изменённых файлов: 164 добавлений и 89 удалений

Просмотреть файл

@ -12,6 +12,7 @@ interface imIAccountBuddy;
interface imIAccount;
interface prplIProtocol;
interface purpleIProxyInfo;
interface nsIScriptError;
/*
* Used to join chat rooms.
@ -162,6 +163,17 @@ interface prplIAccount: nsISupports {
readonly attribute long maxMessageLength;
};
[scriptable, uuid(488959b4-992e-4626-ae96-beaf6adc4a77)]
interface imIDebugMessage: nsISupports {
const short LEVEL_DEBUG = 1;
const short LEVEL_LOG = 2;
const short LEVEL_WARNING = 3;
const short LEVEL_ERROR = 4;
readonly attribute short logLevel; // One of the above constants.
readonly attribute nsIScriptError message;
};
/* This interface should be implemented by the im core. It inherits
from prplIAccount and in most cases will forward the calls for the
inherited members to a prplIAccount account instance implemented by
@ -247,6 +259,12 @@ interface imIAccount: prplIAccount {
readonly attribute boolean connecting;
readonly attribute boolean disconnecting;
void logDebugMessage(in nsIScriptError aMessage, in short aLevel);
/* Get an array of the 50 most recent debug messages. */
void getDebugMessages([optional] out unsigned long aCount,
[retval, array, size_is(aCount)] out imIDebugMessage aMessages);
/* The imIUserStatusInfo instance this account should observe for
status changes. When this is null (the default value), the
account will observe the global status. */

Просмотреть файл

@ -255,6 +255,21 @@ imAccount.prototype = {
this._sendNotification(aTopic, aData);
},
_debugMessages: null,
logDebugMessage: function(aMessage, aLevel) {
if (!this._debugMessages)
this._debugMessages = [];
if (this._debugMessages.length >= 50)
this._debugMessages.shift();
this._debugMessages.push({logLevel: aLevel, message: aMessage});
},
getDebugMessages: function(aCount) {
let messages = this._debugMessages || [];
if (aCount)
aCount.value = messages.length;
return messages;
},
_observedStatusInfo: null,
get observedStatusInfo() this._observedStatusInfo,
_statusObserver: null,

Просмотреть файл

@ -8,9 +8,8 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource:///modules/imXPCOMUtils.jsm");
initLogModule("xhr", this);
function doXHRequest(aUrl, aHeaders, aPOSTData, aOnLoad, aOnError, aThis) {
function doXHRequest(aUrl, aHeaders, aPOSTData, aOnLoad, aOnError, aThis,
aLogger) {
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
xhr.mozBackgroundRequest = true; // no error dialogs
@ -39,7 +38,8 @@ function doXHRequest(aUrl, aHeaders, aPOSTData, aOnLoad, aOnError, aThis) {
xhr.onload = function (aRequest) {
try {
let target = aRequest.target;
DEBUG("Received response: " + target.responseText);
if (aLogger)
aLogger.DEBUG("Received response: " + target.responseText);
if (target.status != 200) {
let errorText = target.responseText;
if (!errorText || /<(ht|\?x)ml\b/i.test(errorText))
@ -69,7 +69,8 @@ function doXHRequest(aUrl, aHeaders, aPOSTData, aOnLoad, aOnError, aThis) {
.join("&");
}
LOG("sending request to " + aUrl + " (POSTData = " + POSTData + ")");
if (aLogger)
aLogger.LOG("sending request to " + aUrl + " (POSTData = " + POSTData + ")");
xhr.send(POSTData);
return xhr;
}

Просмотреть файл

@ -20,11 +20,6 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/imServices.jsm");
const DEBUG_MISC = 1; // Very verbose (= 'DEBUG')
const DEBUG_INFO = 2; // Verbose (= 'LOG')
const DEBUG_WARNING = 3;
const DEBUG_ERROR = 4;
function scriptError(aModule, aLevel, aMessage) {
// Figure out the log level, based on the module and the prefs set.
// The module name is split on periods, and if no pref is set the pref with
@ -39,20 +34,15 @@ function scriptError(aModule, aLevel, aMessage) {
break;
}
}
// Only continue if we want to see this level of logging.
if (logLevel > aLevel)
// Only continue if we will log this message.
if (logLevel > aLevel && (!"imAccount" in this))
return;
dump(aModule + ": " + aMessage + "\n");
// Log a debug statement.
if (aLevel == DEBUG_INFO && logLevel == DEBUG_INFO) {
Services.console.logStringMessage(aMessage);
return;
}
let flag = Ci.nsIScriptError.warningFlag;
if (aLevel >= DEBUG_ERROR)
if (aLevel >= Ci.imIDebugMessage.LEVEL_ERROR)
flag = Ci.nsIScriptError.errorFlag;
let scriptError =
@ -66,15 +56,22 @@ function scriptError(aModule, aLevel, aMessage) {
}
scriptError.init(aMessage, caller.filename, sourceLine, caller.lineNumber,
null, flag, "component javascript");
Services.console.logMessage(scriptError);
if (logLevel <= aLevel) {
if (aLevel == Ci.imIDebugMessage.LEVEL_LOG && logLevel == aLevel)
Services.console.logStringMessage(aMessage);
else
Services.console.logMessage(scriptError);
}
if ("imAccount" in this)
this.imAccount.logDebugMessage(scriptError, aLevel);
}
function initLogModule(aModule, aThis)
{
let obj = aThis || {};
obj.DEBUG = scriptError.bind(obj, aModule, DEBUG_MISC);
obj.LOG = scriptError.bind(obj, aModule, DEBUG_INFO);
obj.WARN = scriptError.bind(obj, aModule, DEBUG_WARNING);
obj.ERROR = scriptError.bind(obj, aModule, DEBUG_ERROR);
obj.DEBUG = scriptError.bind(obj, aModule, Ci.imIDebugMessage.LEVEL_DEBUG);
obj.LOG = scriptError.bind(obj, aModule, Ci.imIDebugMessage.LEVEL_LOG);
obj.WARN = scriptError.bind(obj, aModule, Ci.imIDebugMessage.LEVEL_WARNING);
obj.ERROR = scriptError.bind(obj, aModule, Ci.imIDebugMessage.LEVEL_ERROR);
return obj;
}
XPCOMUtils.defineLazyGetter(Cu.getGlobalForObject({}), "gLogLevels", function() {

Просмотреть файл

@ -19,8 +19,6 @@ const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource:///modules/imXPCOMUtils.jsm");
Cu.import("resource:///modules/imServices.jsm");
initLogModule("jsProtoHelper", this);
XPCOMUtils.defineLazyGetter(this, "_", function()
l10nHelper("chrome://chat/locale/conversations.properties")
);
@ -33,6 +31,7 @@ const GenericAccountPrototype = {
_init: function _init(aProtocol, aImAccount) {
this.protocol = aProtocol;
this.imAccount = aImAccount;
initLogModule(aProtocol.id, this);
},
observe: function(aSubject, aTopic, aData) {},
remove: function() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
@ -146,6 +145,11 @@ const GenericAccountPrototype = {
const GenericAccountBuddyPrototype = {
__proto__: ClassInfo("imIAccountBuddy", "generic account buddy object"),
get DEBUG() this._account.DEBUG,
get LOG() this._account.LOG,
get WARN() this._account.WARN,
get ERROR() this._account.ERROR,
_init: function(aAccount, aBuddy, aTag, aUserName) {
if (!aBuddy && !aUserName)
throw "aUserName is required when aBuddy is null";
@ -342,6 +346,11 @@ const GenericConversationPrototype = {
flags: Ci.nsIClassInfo.DOM_OBJECT,
get wrappedJSObject() this,
get DEBUG() this._account.DEBUG,
get LOG() this._account.LOG,
get WARN() this._account.WARN,
get ERROR() this._account.ERROR,
_init: function(aAccount, aName) {
this._account = aAccount;
this._name = aName;

Просмотреть файл

@ -111,7 +111,7 @@ const Socket = {
if (Services.io.offline)
throw Cr.NS_ERROR_FAILURE;
this.log("Connecting to: " + aHost + ":" + aPort);
this.LOG("Connecting to: " + aHost + ":" + aPort);
this.host = aHost;
this.port = aPort;
@ -144,7 +144,7 @@ const Socket = {
// Disconnect all open streams.
disconnect: function() {
this.log("Disconnect");
this.LOG("Disconnect");
// Close all input and output streams.
if ("_inputStream" in this) {
@ -170,7 +170,7 @@ const Socket = {
// Listen for a connection on a port.
// XXX take a timeout and then call stopListening
listen: function(port) {
this.log("Listening on port " + port);
this.LOG("Listening on port " + port);
this.serverSocket = new ServerSocket(port, false, -1);
this.serverSocket.asyncListen(this);
@ -178,7 +178,7 @@ const Socket = {
// Stop listening for a connection.
stopListening: function() {
this.log("Stop listening");
this.LOG("Stop listening");
// Close the socket to stop listening.
if ("serverSocket" in this)
this.serverSocket.close();
@ -187,7 +187,7 @@ const Socket = {
// Send data on the output stream. Provide aLoggedData to log something
// different than what is actually sent.
sendData: function(/* string */ aData, aLoggedData) {
this.log("Sending:\n" + (aLoggedData || aData));
this.LOG("Sending:\n" + (aLoggedData || aData));
try {
this._outputStream.write(aData + this.delimiter,
@ -200,7 +200,7 @@ const Socket = {
// Send a string to the output stream after converting the encoding. Provide
// aLoggedData to log something different than what is actually sent.
sendString: function(aString, aEncoding, aLoggedData) {
this.log("Sending:\n" + (aLoggedData || aString));
this.LOG("Sending:\n" + (aLoggedData || aString));
let converter = new ScriptableUnicodeConverter();
converter.charset = aEncoding || "UTF-8";
@ -213,7 +213,7 @@ const Socket = {
},
sendBinaryData: function(/* ArrayBuffer */ aData) {
this.log("Sending binary data data: <" + aData + ">");
this.LOG("Sending binary data data: <" + aData + ">");
let uint8 = Uint8Array(aData);
@ -245,17 +245,17 @@ const Socket = {
*/
onProxyAvailable: function(aRequest, aURI, aProxyInfo, aStatus) {
if (!("_proxyCancel" in this)) {
this.log("onProxyAvailable called, but disconnect() was called before.");
this.LOG("onProxyAvailable called, but disconnect() was called before.");
return;
}
if (aProxyInfo) {
if (aProxyInfo.type == "http") {
this.log("ignoring http proxy");
this.LOG("ignoring http proxy");
aProxyInfo = null;
}
else {
this.log("using " + aProxyInfo.type + " proxy: " +
this.LOG("using " + aProxyInfo.type + " proxy: " +
aProxyInfo.host + ":" + aProxyInfo.port);
}
}
@ -268,7 +268,7 @@ const Socket = {
*/
// Called after a client connection is accepted when we're listening for one.
onSocketAccepted: function(aServerSocket, aTransport) {
this.log("onSocketAccepted");
this.LOG("onSocketAccepted");
// Store the values
this.transport = aTransport;
this.host = this.transport.host;
@ -284,7 +284,7 @@ const Socket = {
// Called when the listening socket stops for some reason.
// The server socket is effectively dead after this notification.
onStopListening: function(aSocket, aStatus) {
this.log("onStopListening");
this.LOG("onStopListening");
if ("serverSocket" in this)
delete this.serverSocket;
},
@ -302,7 +302,7 @@ const Socket = {
.readByteArray(aCount));
let size = this.inputSegmentSize || this._incomingDataBuffer.length;
this.log(size + " " + this._incomingDataBuffer.length);
this.LOG(size + " " + this._incomingDataBuffer.length);
while (this._incomingDataBuffer.length >= size) {
let buffer = new ArrayBuffer(size);
@ -338,11 +338,11 @@ const Socket = {
*/
// Signifies the beginning of an async request
onStartRequest: function(aRequest, aContext) {
this.log("onStartRequest");
this.DEBUG("onStartRequest");
},
// Called to signify the end of an asynchronous request.
onStopRequest: function(aRequest, aContext, aStatus) {
this.log("onStopRequest (" + aStatus + ")");
this.DEBUG("onStopRequest (" + aStatus + ")");
delete this.isConnected;
if (aStatus == NS_ERROR_NET_RESET)
this.onConnectionReset();
@ -386,7 +386,7 @@ const Socket = {
0x804b0006: "STATUS_RECEIVING_FROM"
};
let status = nsITransportEventSinkStatus[aStatus];
this.log("onTransportStatus(" + (status || ("0x" + aStatus.toString(16))) +")");
this.DEBUG("onTransportStatus(" + (status || ("0x" + aStatus.toString(16))) +")");
if (status == "STATUS_CONNECTED_TO") {
this.isConnected = true;
@ -477,7 +477,8 @@ const Socket = {
********************* Methods for subtypes to override **********************
*****************************************************************************
*/
log: function(aString) { },
LOG: function(aString) { },
DEBUG: function(aString) { },
// Called when a connection is established.
onConnection: function() { },
// Called when a socket is accepted after listening.

Просмотреть файл

@ -393,7 +393,7 @@ Account.prototype = {
return;
}
LOG("Connecting using existing token");
this.LOG("Connecting using existing token");
this.getTimelines();
},
@ -465,7 +465,7 @@ Account.prototype = {
"OAuth " + params.map(function (p) p[0] + "=\"" + p[1] + "\"").join(", ");
let headers = (aHeaders || []).concat([["Authorization", authorization]]);
return doXHRequest(url, headers, aPOSTData, aOnLoad, aOnError, aThis);
return doXHRequest(url, headers, aPOSTData, aOnLoad, aOnError, aThis, this);
},
_parseURLData: function(aData) {
let result = {};
@ -539,7 +539,7 @@ Account.prototype = {
this._lastMsgId = lastMsgId;
}
else
WARN("invalid value for the lastMessageId preference: " + lastMsgId);
this.WARN("invalid value for the lastMessageId preference: " + lastMsgId);
}
let getParams = "?include_entities=1&count=200" + lastMsgParam;
this._pendingRequests = [
@ -556,7 +556,7 @@ Account.prototype = {
let url = "http://search.twitter.com/search.json" + getParams;
this._pendingRequests.push(doXHRequest(url, null, null,
this.onSearchResultsReceived,
this.onTimelineError, this));
this.onTimelineError, this, this));
}
},
@ -586,7 +586,7 @@ Account.prototype = {
},
onTimelineError: function(aError, aResponseText, aRequest) {
ERROR(aError);
this.ERROR(aError);
if (aRequest.status == 401)
++this._timelineAuthError;
this._doneWithTimelineRequest(aRequest);
@ -731,7 +731,7 @@ Account.prototype = {
onDataAvailable: function(aRequest) {
this.resetStreamTimeout();
let newText = this._pendingData + aRequest.target.response;
DEBUG("Received data: " + newText);
this.DEBUG("Received data: " + newText);
let messages = newText.split(/\r\n?/);
this._pendingData = messages.pop();
for each (let message in messages) {
@ -741,7 +741,7 @@ Account.prototype = {
try {
msg = JSON.parse(message);
} catch (e) {
ERROR(e + " while parsing " + message);
this.ERROR(e + " while parsing " + message);
continue;
}
if ("text" in msg)
@ -784,7 +784,7 @@ Account.prototype = {
oauthParams);
},
onRequestTokenReceived: function(aData) {
LOG("Received request token.");
this.LOG("Received request token.");
let data = this._parseURLData(aData);
if (!data.oauth_callback_confirmed ||
!data.oauth_token || !data.oauth_token_secret) {
@ -883,7 +883,7 @@ Account.prototype = {
[["oauth_verifier", aTokenVerifier]]);
},
onAccessTokenReceived: function(aData) {
LOG("Received access token.");
this.LOG("Received access token.");
let result = this._parseURLData(aData);
if (!this.fixAccountName(result))
return;
@ -909,8 +909,8 @@ Account.prototype = {
return false;
}
LOG("Fixing the case of the account name: " +
this.name + " -> " + aAuthResult.screen_name);
this.LOG("Fixing the case of the account name: " +
this.name + " -> " + aAuthResult.screen_name);
this.__defineGetter__("name", function() aAuthResult.screen_name);
return true;
},
@ -972,8 +972,8 @@ Account.prototype = {
const kMaxUserDescriptionLength = 160;
if (aDescription.length > kMaxUserDescriptionLength) {
aDescription = aDescription.substr(0, kMaxUserDescriptionLength);
WARN("Description too long (over " + kMaxUserDescriptionLength +
" characters):\n" + aDescription + ".");
this.WARN("Description too long (over " + kMaxUserDescriptionLength +
" characters):\n" + aDescription + ".");
this.timeline.systemMessage(_("error.descriptionTooLong", aDescription));
}
// Don't need to catch the reply since the stream receives user_update.

Просмотреть файл

@ -11,8 +11,6 @@ Cu.import("resource:///modules/socket.jsm");
Cu.import("resource:///modules/xmpp-xml.jsm");
Cu.import("resource:///modules/xmpp-authmechs.jsm");
initLogModule("xmpp-session", this);
XPCOMUtils.defineLazyGetter(this, "_", function()
l10nHelper("chrome://chat/locale/xmpp.properties")
);
@ -90,6 +88,11 @@ XMPPSession.prototype = {
delete this._disconnectTimer;
},
get DEBUG() this._account.DEBUG,
get LOG() this._account.LOG,
get WARN() this._account.WARN,
get ERROR() this._account.ERROR,
_security: null,
_encrypted: false,
@ -180,9 +183,6 @@ XMPPSession.prototype = {
this.sendStanza(s);
},
/* Log a message (called by the socket code) */
log: LOG,
/* Socket events */
/* The connection is established */
onConnection: function() {
@ -234,9 +234,9 @@ XMPPSession.prototype = {
/* Methods called by the XMPPParser instance */
onXMLError: function(aError, aException) {
if (aError == "parsing-characters")
WARN(aError + ": " + aException + "\n" + this._lastReceivedData);
this.WARN(aError + ": " + aException + "\n" + this._lastReceivedData);
else
ERROR(aError + ": " + aException + "\n" + this._lastReceivedData);
this.ERROR(aError + ": " + aException + "\n" + this._lastReceivedData);
if (aError != "parse-warning" && aError != "parsing-characters")
this._networkError(_("connection.error.receivedUnexpectedData"));
},
@ -246,7 +246,7 @@ XMPPSession.prototype = {
stanzaListeners: {
initStream: function(aStanza) {
if (aStanza.localName != "features") {
ERROR("Unexpected stanza " + aStanza.localName + ", expected 'features'");
this.ERROR("Unexpected stanza " + aStanza.localName + ", expected 'features'");
this._networkError(_("connection.error.incorrectResponse"));
return;
}
@ -287,7 +287,7 @@ XMPPSession.prototype = {
},
startAuth: function(aStanza) {
if (aStanza.localName != "features") {
ERROR("Unexpected stanza " + aStanza.localName + ", expected 'features'");
this.ERROR("Unexpected stanza " + aStanza.localName + ", expected 'features'");
this._networkError(_("connection.error.incorrectResponse"));
return;
}
@ -367,7 +367,7 @@ XMPPSession.prototype = {
try {
result = this._auth.next(aStanza);
} catch(e) {
ERROR(e);
this.ERROR(e);
this.onError(Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED,
_("connection.error.authenticationFailure"));
return;
@ -390,7 +390,7 @@ XMPPSession.prototype = {
},
startBind: function(aStanza) {
if (!aStanza.getElement(["bind"])) {
ERROR("Unexpected lack of the bind feature");
this.ERROR("Unexpected lack of the bind feature");
this._networkError(_("connection.error.incorrectResponse"));
return;
}
@ -409,7 +409,7 @@ XMPPSession.prototype = {
return;
}
jid = jid.innerText;
DEBUG("jid = " + jid);
this.DEBUG("jid = " + jid);
this._jid = this._account._parseJID(jid);
this.startSession();
},
@ -530,6 +530,6 @@ XMPPSession.prototype = {
}
},
onXmppStanza: function(aStanza) {
ERROR("should not be reached\n");
this.ERROR("should not be reached\n");
}
};

Просмотреть файл

@ -321,7 +321,7 @@ XMPPParser.prototype = {
},
_logReceivedData: function(aData) {
this._listener.log("received:\n" + aData);
this._listener.LOG("received:\n" + aData);
},
_inOnDataAvailable: false,
onDataAvailable: function(aInputStream, aOffset, aCount) {

Просмотреть файл

@ -35,8 +35,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "imgTools",
"@mozilla.org/image/tools;1",
"imgITools");
initLogModule("xmpp", this);
XPCOMUtils.defineLazyGetter(this, "_", function()
l10nHelper("chrome://chat/locale/xmpp.properties")
);
@ -112,8 +110,8 @@ const XMPPMUCConversationPrototype = {
let nick = this._account._parseJID(from).resource;
if (aStanza.attributes["type"] == "unavailable") {
if (!(nick in this._participants)) {
WARN("received unavailable presence for an unknown MUC participant: " +
from);
this.WARN("received unavailable presence for an unknown MUC participant: " +
from);
return;
}
delete this._participants[nick];
@ -369,8 +367,8 @@ const XMPPAccountBuddyPrototype = {
get serverAlias() this._rosterAlias || this._vCardFormattedName || this._serverAlias,
set serverAlias(aNewAlias) {
if (!this._rosterItem) {
ERROR("attempting to update the server alias of an account buddy for " +
"which we haven't received a roster item.");
this.ERROR("attempting to update the server alias of an account buddy " +
"for which we haven't received a roster item.");
return;
}
@ -396,7 +394,7 @@ const XMPPAccountBuddyPrototype = {
set tag(aNewTag) {
let oldTag = this._tag;
if (oldTag.name == aNewTag.name) {
ERROR("attempting to set the tab to the same value");
this.ERROR("attempting to set the tag to the same value");
return;
}
@ -404,7 +402,7 @@ const XMPPAccountBuddyPrototype = {
Services.contacts.accountBuddyMoved(this, oldTag, aNewTag);
if (!this._rosterItem) {
ERROR("attempting to change the tag of an account buddy without roster item");
this.ERROR("attempting to change the tag of an account buddy without roster item");
return;
}
@ -757,7 +755,7 @@ const XMPPAccountPrototype = {
if (this._buddies.hasOwnProperty(jid)) {
let subscription = this._buddies[jid].subscription;
if (subscription && (subscription == "both" || subscription == "to")) {
DEBUG("not re-adding an existing buddy");
this.DEBUG("not re-adding an existing buddy");
return;
}
}
@ -824,7 +822,7 @@ const XMPPAccountPrototype = {
/* Called when a presence stanza is received */
onPresenceStanza: function(aStanza) {
let from = aStanza.attributes["from"];
DEBUG("Received presence stanza for " + from);
this.DEBUG("Received presence stanza for " + from);
let jid = this._normalizeJID(from);
let type = aStanza.attributes["type"];
@ -868,7 +866,7 @@ const XMPPAccountPrototype = {
// We have attempted to join, but not created the conversation yet.
if (aStanza.attributes["type"] == "error") {
delete this._mucs[jid];
ERROR("Failed to join MUC: " + aStanza.convertToString());
this.ERROR("Failed to join MUC: " + aStanza.convertToString());
return;
}
let nick = this._mucs[jid];
@ -877,7 +875,7 @@ const XMPPAccountPrototype = {
this._mucs[jid].onPresenceStanza(aStanza);
}
else if (from != this._connection._jid.jid)
WARN("received presence stanza for unknown buddy " + from);
this.WARN("received presence stanza for unknown buddy " + from);
},
/* Called when a message stanza is received */
@ -914,7 +912,7 @@ const XMPPAccountPrototype = {
if (type == "groupchat" ||
(type == "error" && this._mucs.hasOwnProperty(norm))) {
if (!this._mucs.hasOwnProperty(norm)) {
WARN("Received a groupchat message for unknown MUC " + norm);
this.WARN("Received a groupchat message for unknown MUC " + norm);
return;
}
this._mucs[norm].incomingMessage(body, aStanza, date);
@ -939,7 +937,7 @@ const XMPPAccountPrototype = {
if (s.length > 0)
state = s[0].localName;
if (state) {
DEBUG(state);
this.DEBUG(state);
if (state == "active")
this._conv[norm].updateTyping(Ci.prplIConvIM.NOT_TYPING);
else if (state == "composing")
@ -1017,7 +1015,7 @@ const XMPPAccountPrototype = {
_onRosterItem: function(aItem, aNotifyOfUpdates) {
let jid = aItem.attributes["jid"];
if (!jid) {
WARN("Received a roster item without jid: " + aItem.getXML());
this.WARN("Received a roster item without jid: " + aItem.getXML());
return "";
}
jid = this._normalizeJID(jid);
@ -1146,7 +1144,7 @@ const XMPPAccountPrototype = {
/* Create a new conversation */
createConversation: function(aNormalizedName) {
if (!this._buddies.hasOwnProperty(aNormalizedName)) {
ERROR("Trying to create a conversation; buddy not present: " + aNormalizedName);
this.ERROR("Trying to create a conversation; buddy not present: " + aNormalizedName);
return null;
}
@ -1396,6 +1394,6 @@ const XMPPAccountPrototype = {
if (this._userVCard.getXML() != existingVCard)
this._connection.sendStanza(Stanza.iq("set", null, null, this._userVCard));
else
LOG("Not sending the vCard because the server stored vCard is identical.");
this.LOG("Not sending the vCard because the server stored vCard is identical.");
}
};

Просмотреть файл

@ -2,7 +2,7 @@
* 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/. */
const {interfaces: Ci, utils: Cu} = Components;
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource:///modules/imServices.jsm");
Cu.import("resource://gre/modules/DownloadUtils.jsm");
@ -207,6 +207,34 @@ var gAccountManager = {
account.disconnect();
}
},
copyDebugLog: function am_copyDebugLog() {
let account = this.accountList.selectedItem.account;
let text = account.getDebugMessages().map(function(dbgMsg) {
let m = dbgMsg.message;
const dateServ = Cc["@mozilla.org/intl/scriptabledateformat;1"]
.getService(Ci.nsIScriptableDateFormat);
let time = new Date(m.timeStamp);
time = dateServ.FormatDateTime("", dateServ.dateFormatShort,
dateServ.timeFormatSeconds,
time.getFullYear(), time.getMonth() + 1,
time.getDate(), time.getHours(),
time.getMinutes(), time.getSeconds());
let level = dbgMsg.logLevel;
if (level == dbgMsg.LEVEL_ERROR)
level = "ERROR";
else if (level == dbgMsg.LEVEL_WARNING)
level = "WARN.";
else if (level == dbgMsg.LEVEL_LOG)
level = "LOG ";
else
level = "DEBUG"
return "[" + time + "] " + level + " (@ " + m.sourceLine +
" " + m.sourceName + ":" + m.lineNumber + ")\n" +
m.errorMessage;
}).join("\n");
Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper).copyString(text);
},
updateConnectedLabels: function am_updateConnectedLabels() {
for (let i = 0; i < gAccountManager.accountList.itemCount; ++i) {
let item = gAccountManager.accountList.getItemAtIndex(i);
@ -473,7 +501,7 @@ var gAccountManager = {
If none, this function has already returned */
case as.AUTOLOGIN_ENABLED:
if (!("PluralForm" in window))
Components.utils.import("resource://gre/modules/PluralForm.jsm");
Cu.import("resource://gre/modules/PluralForm.jsm");
label = bundle.getString("accountsManager.notification.singleCrash.label");
label = PluralForm.get(crashCount, label).replace("#1", crashCount);
priority = box.PRIORITY_WARNING_MEDIUM;

Просмотреть файл

@ -48,6 +48,10 @@
label="&account.cancelReconnection.label;"
accesskey="&account.cancelReconnection.accesskey;"
oncommand="gAccountManager.cancelReconnection()"/>
<command id="cmd_copyDebugLog"
label="&account.copyDebugLog.label;"
accesskey="&account.copyDebugLog.accesskey;"
oncommand="gAccountManager.copyDebugLog();"/>
<command id="cmd_moveup"
label="&account.moveup.label;"
oncommand="gAccountManager.moveCurrentItem(-1)"/>
@ -98,6 +102,8 @@
<menuitem id="context_cancelReconnection"
command="cmd_cancelReconnection"
observes="contextAccountsItems"/>
<menuitem id="context_copyDebugLog"
command="cmd_copyDebugLog"/>
<menuseparator id="context_accountsItemsSeparator"
observes="contextAccountsItems"/>
<menuitem command="cmd_new"/>

Просмотреть файл

@ -27,6 +27,8 @@
<!ENTITY account.movedown.label "Move down">
<!ENTITY account.cancelReconnection.label "Cancel reconnection">
<!ENTITY account.cancelReconnection.accesskey "A">
<!ENTITY account.copyDebugLog.label "Copy Debug Log">
<!ENTITY account.copyDebugLog.accesskey "C">
<!ENTITY account.connecting "Connecting…">
<!ENTITY account.disconnecting "Disconnecting…">
<!ENTITY account.disconnected "Not Connected">