diff --git a/chat/chat-prefs.js b/chat/chat-prefs.js --- a/chat/chat-prefs.js +++ b/chat/chat-prefs.js @@ -5,18 +5,18 @@ pref("messenger.startup.action", 1); pref("messenger.accounts", ""); // Should the accounts service stored in the password manager the // passwords that are currently stored in the preferences? pref("messenger.accounts.convertOldPasswords", false); -// The intervals in seconds between automatic reconnection attempts -// The last value will be reused forever. +// The intervals in seconds between automatic reconnection attempts. +// The last value will be reused for the rest of the reconnection attempts. // A value of 0 means that there will be no more reconnection attempts. pref("messenger.accounts.reconnectTimer", "1,5,30,60,90,300,600,1200,3600"); // List of tags ids whose contacts should be shown in the special // "Other contacts" group. pref("messenger.buddies.hiddenTags", ""); // 1 accepts invitations automatically, diff --git a/chat/components/public/imIAccount.idl b/chat/components/public/imIAccount.idl --- a/chat/components/public/imIAccount.idl +++ b/chat/components/public/imIAccount.idl @@ -206,18 +206,18 @@ the protocol plugin. */ [scriptable, uuid(20a85b44-e220-4f23-85bf-f8523d1a2b08)] interface imIAccount: prplIAccount { /* Check if autologin is enabled for this account, connect it now. */ void checkAutoLogin(); /* Delete the account (from the preferences, mozStorage, and call unInit). */ void remove(); - /* Cancel the timer that automatically reconnects the account that were - disconnected with a non fatal error */ + /* Cancel the timer that automatically reconnects the account if it was + disconnected because of a non fatal error. */ void cancelReconnection(); readonly attribute AUTF8String name; readonly attribute AUTF8String id; readonly attribute PRUint32 numericId; readonly attribute prplIProtocol protocol; readonly attribute prplIAccount prplAccount; diff --git a/chat/components/public/imIContactsService.idl b/chat/components/public/imIContactsService.idl --- a/chat/components/public/imIContactsService.idl +++ b/chat/components/public/imIContactsService.idl @@ -158,18 +158,18 @@ interface imIContact: imIStatusInfo { * See also the comment above the 'id' attribute. * contact-icon-changed * * Observers will also receive all the (forwarded) notifications * from the linked buddies (imIBuddy instances) and their account * buddies (imIAccountBuddy instances). */ - // Exposed for add-on authors. All usage by Instantbird will come from - // the imIContact implementation so it wasn't required to expose this. + // Exposed for add-on authors. All internal calls will come from the + // imIContact implementation itself so it wasn't required to expose this. // This can be used to dispatch custom notifications to the // observers of the contact and its tags. // The notification will also be forwarded to the observer service. void notifyObservers(in nsISupports aObj, in string aEvent, [optional] in wstring aData); }; @@ -207,18 +207,18 @@ interface imIBuddy: imIStatusInfo { * buddy-preferred-account-changed * The account that would be favored to start a conversation has changed. * buddy-icon-changed * * Observers will also receive all the (forwarded) notifications * from the linked account buddies (imIAccountBuddy instances). */ - // Exposed for add-on authors. All usage by Instantbird will come from - // the imIBuddy implementation so it wasn't required to expose this. + // Exposed for add-on authors. All internal calls will come from the + // imIBuddy implementation itself so it wasn't required to expose this. // This can be used to dispatch custom notifications to the // observers of the buddy, its contact and its tags. // The contact will forward the notifications to the observer service. void notifyObservers(in nsISupports aObj, in string aEvent, [optional] in wstring aData); // observe should only be called by the imIAccountBuddy // implementations to report changes. diff --git a/chat/components/public/imITagsService.idl b/chat/components/public/imITagsService.idl --- a/chat/components/public/imITagsService.idl +++ b/chat/components/public/imITagsService.idl @@ -55,18 +55,18 @@ interface imITag: nsISupports { void addObserver(in nsIObserver aObserver); void removeObserver(in nsIObserver aObserver); /* Observers will be notified of changes related to the contacts * that have the tag: contact-*, buddy-*, account-buddy-* * notifications forwarded respectively from the imIContact, * imIBuddy and imIAccountBuddy instances. */ - // Exposed for add-on authors. All usage by Instantbird will come from - // the imITag implementation so it wasn't required to expose this. + // Exposed for add-on authors. All internal calls will come from the + // imITag implementation itself so it wasn't required to expose this. // This can be used to dispatch custom notifications to the // observers of the tag. void notifyObservers(in nsISupports aObj, in string aEvent, [optional] in wstring aData); }; [scriptable, uuid(f799a9c2-23f2-4fd1-96fb-515bad238f8c)] interface imITagsService: nsISupports { diff --git a/chat/components/public/prplIMessage.idl b/chat/components/public/prplIMessage.idl --- a/chat/components/public/prplIMessage.idl +++ b/chat/components/public/prplIMessage.idl @@ -62,17 +62,17 @@ interface prplIMessage: nsISupports { readonly attribute AUTF8String originalMessage; attribute AUTF8String message; readonly attribute AUTF8String iconURL; readonly attribute PRTime time; readonly attribute prplIConversation conversation; /* Holds the sender color for Chats. Empty string by default, it is set by the conversation binding. */ - attribute AUTF8String color; + attribute AUTF8String color; /* PURPLE_MESSAGE_SEND = 0x0001, /**< Outgoing message. */ readonly attribute boolean outgoing; /* PURPLE_MESSAGE_RECV = 0x0002, /**< Incoming message. */ readonly attribute boolean incoming; /* PURPLE_MESSAGE_SYSTEM = 0x0004, /**< System message. */ readonly attribute boolean system; /* PURPLE_MESSAGE_AUTO_RESP = 0x0008, /**< Auto response. */ diff --git a/chat/components/src/Makefile.in b/chat/components/src/Makefile.in --- a/chat/components/src/Makefile.in +++ b/chat/components/src/Makefile.in @@ -42,18 +42,17 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk EXTRA_COMPONENTS = \ imAccounts.manifest \ imCommands.js imCommands.manifest \ imContacts.js imContacts.manifest \ imConversations.js imConversations.manifest \ imCore.js imCore.manifest \ - logger.manifest \ + logger.js logger.manifest \ smileProtocolHandler.js smileProtocolHandler.manifest \ $(NULL) EXTRA_PP_COMPONENTS = \ imAccounts.js \ - logger.js \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/chat/components/src/imAccounts.js b/chat/components/src/imAccounts.js --- a/chat/components/src/imAccounts.js +++ b/chat/components/src/imAccounts.js @@ -783,19 +783,17 @@ AccountsService.prototype = { prefs.deleteBranch(kPrefAutologinPending); #ifdef MOZ_CRASHREPORTER try { // Try to get more info with breakpad let lastCrashTime = 0; /* Locate the LastCrash file */ - let lastCrash = - Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties) - .get("UAppData", Ci.nsILocalFile); + let lastCrash = Services.dirsvc.get("UAppData", Ci.nsILocalFile); lastCrash.append("Crash Reports"); lastCrash.append("LastCrash"); if (lastCrash.exists()) { /* Ok, the file exists, now let's try to read it */ let is = Cc["@mozilla.org/network/file-input-stream;1"] .createInstance(Ci.nsIFileInputStream); let sis = Cc["@mozilla.org/scriptableinputstream;1"] .createInstance(Ci.nsIScriptableInputStream); diff --git a/chat/components/src/imCommands.js b/chat/components/src/imCommands.js --- a/chat/components/src/imCommands.js +++ b/chat/components/src/imCommands.js @@ -30,105 +30,99 @@ * 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 ***** */ -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource:///modules/imServices.jsm"); +const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components; -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; +Cu.import("resource:///modules/imServices.jsm"); +Cu.import("resource:///modules/imXPCOMUtils.jsm"); -XPCOMUtils.defineLazyServiceGetter(this, "obs", - "@mozilla.org/observer-service;1", - "nsIObserverService"); - -XPCOMUtils.defineLazyGetter(this, "bundle", function() - Services.strings.createBundle("chrome://chat/locale/commands.properties") +XPCOMUtils.defineLazyGetter(this, "_", function() + l10nHelper("chrome://chat/locale/commands.properties") ); function CommandsService() { } CommandsService.prototype = { initCommands: function() { this._commands = {}; // The say command is directly implemented in the UI layer, but has a // dummy command registered here so it shows up as a command (e.g. when // using the /help command). this.registerCommand({ name: "say", - get helpString() bundle.GetStringFromName("sayHelpString"), + get helpString() _("sayHelpString"), usageContext: Ci.imICommand.CONTEXT_ALL, priority: Ci.imICommand.PRIORITY_HIGH, run: function(aMsg, aConv) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; } }); this.registerCommand({ name: "raw", - get helpString() bundle.GetStringFromName("rawHelpString"), + get helpString() _("rawHelpString"), usageContext: Ci.imICommand.CONTEXT_ALL, priority: Ci.imICommand.PRIORITY_DEFAULT, run: function(aMsg, aConv) { aConv.sendMsg(aMsg); return true; } }); this.registerCommand({ // Reference the command service so we can use the internal properties // directly. cmdSrv: this, name: "help", - get helpString() bundle.GetStringFromName("helpHelpString"), + get helpString() _("helpHelpString"), usageContext: Ci.imICommand.CONTEXT_ALL, priority: Ci.imICommand.PRIORITY_DEFAULT, run: function(aMsg, aConv) { let conv = Services.conversations.getUIConversation(aConv); if (!conv) return false; // Handle when no command is given, list all possible commands that are // available for this conversation (alphabetically). if (!aMsg) { let commands = this.cmdSrv.listCommandsForConversation(aConv, {}); if (!commands.length) return false; // Concatenate the command names (separated by a comma and space). let cmds = commands.map(function(aCmd) aCmd.name).sort().join(", "); - let message = bundle.formatStringFromName("commands", [cmds], 1); + let message = _("commands", cmds); // Display the message conv.systemMessage(message); return true; } // A command name was given, find the commands that match. let cmdArray = this.cmdSrv._findCommands(aConv, aMsg); if (!cmdArray.length) { // No command that matches. - let message = bundle.formatStringFromName("noCommand", [aMsg], 1); + let message = _("noCommand", aMsg); conv.systemMessage(message); return true; } // Only show the help for the one of the highest priority. let cmd = cmdArray[0]; let text = cmd.helpString; if (!text) - text = bundle.formatStringFromName("noHelp", [cmd.name], 1); + text = _("noHelp", cmd.name); // Display the message. conv.systemMessage(text); return true; } }); // Status commands @@ -138,21 +132,17 @@ CommandsService.prototype = { busy: "UNAVAILABLE", dnd: "UNAVAILABLE", offline: "OFFLINE" }; for (let cmd in status) { let statusValue = Ci.imIStatusInfo["STATUS_" + status[cmd]]; this.registerCommand({ name: cmd, - get helpString() - bundle.formatStringFromName("statusCommand", - [this.name, - bundle.GetStringFromName(this.name)], - 2), + get helpString() _("statusCommand", this.name, _(this.name)), usageContext: Ci.imICommand.CONTEXT_ALL, priority: Ci.imICommand.PRIORITY_HIGH, run: function(aMsg) { Services.core.globalUserStatus.setStatus(statusValue, aMsg); return true; } }); } diff --git a/chat/components/src/imContacts.js b/chat/components/src/imContacts.js --- a/chat/components/src/imContacts.js +++ b/chat/components/src/imContacts.js @@ -39,19 +39,17 @@ const {classes: Cc, interfaces: Ci, util Cu.import("resource:///modules/imXPCOMUtils.jsm"); Cu.import("resource:///modules/imServices.jsm"); var gDBConnection = null; function getDBConnection() { const NS_APP_USER_PROFILE_50_DIR = "ProfD"; - let dbFile = - Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties) - .get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile); + let dbFile = Services.dirsvc.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile); dbFile.append("blist.sqlite"); let conn = Cc["@mozilla.org/storage/service;1"].getService(Ci.mozIStorageService) .openDatabase(dbFile); if (!conn.connectionReady) throw Cr.NS_ERROR_UNEXPECTED; @@ -188,17 +186,17 @@ function Tag(aId, aName) { this._observers = []; TagsById[this.id] = this; } Tag.prototype = { get id() this._id, get name() this._name, set name(aNewName) { - var statement = DBConn.createStatement("UPDATE tags SET name = :name WHERE id = :id"); + let statement = DBConn.createStatement("UPDATE tags SET name = :name WHERE id = :id"); statement.params.name = aNewName; statement.params.id = this._id; statement.execute(); //FIXME move the account buddies if some use this tag as their group return aNewName; }, getContacts: function(aContactCount) { @@ -224,17 +222,17 @@ Tag.prototype = { this._observers = this._observers.filter(function(o) o !== aObserver); }, notifyObservers: function(aSubject, aTopic, aData) { for each (let observer in this._observers) observer.observe(aSubject, aTopic, aData); }, getInterfaces: function(countRef) { - var interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.imITag]; + let interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.imITag]; countRef.value = interfaces.length; return interfaces; }, getHelperForLanguage: function(language) null, implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT, flags: 0, QueryInterface: XPCOMUtils.generateQI([Ci.imITag, Ci.nsIClassInfo]) }; @@ -354,17 +352,17 @@ var otherContactsTag = { this._observers = this._observers.filter(function(o) o !== aObserver); }, notifyObservers: function(aSubject, aTopic, aData) { for each (let observer in this._observers) observer.observe(aSubject, aTopic, aData); }, getInterfaces: function(countRef) { - var interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.nsIObserver, Ci.imITag]; + let interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.nsIObserver, Ci.imITag]; countRef.value = interfaces.length; return interfaces; }, getHelperForLanguage: function(language) null, implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT, flags: 0, QueryInterface: XPCOMUtils.generateQI([Ci.imITag, Ci.nsIObserver, Ci.nsIClassInfo]) }; @@ -876,17 +874,17 @@ Contact.prototype = { this._notifyObservers("added"); break; case "buddy-removed": this._removeBuddy(aSubject); } }, getInterfaces: function(countRef) { - var interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.imIContact]; + let interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.imIContact]; countRef.value = interfaces.length; return interfaces; }, getHelperForLanguage: function(language) null, implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT, flags: 0, QueryInterface: XPCOMUtils.generateQI([Ci.imIContact, Ci.nsIClassInfo]) }; @@ -1186,31 +1184,31 @@ Buddy.prototype = { } this.contact._moved(aSubject.tag); } break; } }, getInterfaces: function(countRef) { - var interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.imIBuddy]; + let interfaces = [Ci.nsIClassInfo, Ci.nsISupports, Ci.imIBuddy]; countRef.value = interfaces.length; return interfaces; }, getHelperForLanguage: function(language) null, implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT, flags: 0, QueryInterface: XPCOMUtils.generateQI([Ci.imIBuddy, Ci.nsIClassInfo]) }; function ContactsService() { } ContactsService.prototype = { initContacts: function() { - var statement = DBConn.createStatement("SELECT id, name FROM tags"); + let statement = DBConn.createStatement("SELECT id, name FROM tags"); while (statement.executeStep()) Tags.push(new Tag(statement.getInt32(0), statement.getUTF8String(1))); statement = DBConn.createStatement("SELECT id, alias FROM contacts"); while (statement.executeStep()) new Contact(statement.getInt32(0), statement.getUTF8String(1)); statement = @@ -1248,21 +1246,21 @@ ContactsService.prototype = { "account_id = " + accountId + ", buddy_id = " + buddyId + ", tag_id = " + tagId); continue; } let account = Services.accounts.getAccountByNumericId(accountId); let tag = TagsById[tagId]; try { - let ab = account.loadBuddy(buddy, tag); - if (ab) - buddy._addAccount(ab, tag); + let accountBuddy = account.loadBuddy(buddy, tag); + if (accountBuddy) + buddy._addAccount(accountBuddy, tag); } catch (e) { - // FIXME ab shouldn't be NULL (once purpleAccount is finished) + // FIXME accountBuddy shouldn't be NULL (once imAccounts.js is finished) // It currently doesn't work right with unknown protocols. Components.utils.reportError(e); dump(e + "\n"); } } otherContactsTag._initHiddenTags(); }, diff --git a/chat/components/src/imCore.js b/chat/components/src/imCore.js --- a/chat/components/src/imCore.js +++ b/chat/components/src/imCore.js @@ -192,18 +192,17 @@ UserStatus.prototype = { if (aStatus != Ci.imIStatusInfo.STATUS_UNKNOWN) this._statusType = aStatus; if (aStatus != Ci.imIStatusInfo.STATUS_OFFLINE) this._statusText = aMessage; this._notifyObservers("status-changed", aMessage); }, _getProfileDir: function() - Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties) - .get("ProfD" /*NS_APP_USER_PROFILE_50_DIR*/, Ci.nsIFile), + Services.dirsvc.get("ProfD", Ci.nsIFile), setUserIcon: function(aIconFile) { let folder = this._getProfileDir(); let newName = ""; if (aIconFile) { // Get the extension (remove trailing dots - invalid Windows extension). let ext = aIconFile.leafName.replace(/.*(\.[a-z0-9]+)\.*/i, "$1"); // newName = userIcon-. diff --git a/chat/components/src/logger.js b/chat/components/src/logger.js --- a/chat/components/src/logger.js +++ b/chat/components/src/logger.js @@ -30,53 +30,38 @@ * 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 ***** */ -#filter substitution -#ifdef XP_WIN -#define LINE_BREAK \r\n -#else -#define LINE_BREAK \n -#endif +const {classes: Cc, interfaces: Ci, utils: Cu, Constructor: CC} = Components; -Components.utils.import("resource:///modules/hiddenWindow.jsm"); -Components.utils.import("resource:///modules/imServices.jsm"); -Components.utils.import("resource:///modules/imXPCOMUtils.jsm"); -Components.utils.import("resource:///modules/jsProtoHelper.jsm"); +Cu.import("resource:///modules/hiddenWindow.jsm"); +Cu.import("resource:///modules/imServices.jsm"); +Cu.import("resource:///modules/imXPCOMUtils.jsm"); +Cu.import("resource:///modules/jsProtoHelper.jsm"); -const Cc = Components.classes; -const Ci = Components.interfaces; -const CC = Components.Constructor; - -XPCOMUtils.defineLazyServiceGetter(this, "obs", - "@mozilla.org/observer-service;1", - "nsIObserverService"); -XPCOMUtils.defineLazyServiceGetter(this, "prefs", - "@mozilla.org/preferences-service;1", - "nsIPrefBranch"); XPCOMUtils.defineLazyGetter(this, "logDir", function() { - let file = Components.classes["@mozilla.org/file/directory_service;1"] - .getService(Components.interfaces.nsIProperties) - .get("ProfD", Components.interfaces.nsIFile); + let file = Services.dirsvc.get("ProfD", Ci.nsIFile); file.append("logs"); return file; }); const FileInputStream = CC("@mozilla.org/network/file-input-stream;1", "nsIFileInputStream", "init"); const ConverterInputStream = CC("@mozilla.org/intl/converter-input-stream;1", "nsIConverterInputStream", "init"); +const kLineBreak = "@mozilla.org/windows-registry-key;1" in Cc ? "\r\n" : "\n"; + function getLogFolderForAccount(aAccount, aCreate) { let file = logDir.clone(); function createIfNotExists(aFile) { if (aCreate && !aFile.exists()) aFile.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); } createIfNotExists(file); @@ -115,17 +100,17 @@ function ConversationLog(aConversation) ConversationLog.prototype = { _log: null, format: "txt", _init: function cl_init() { let file = getLogFolderForAccount(this._conv.account, true); file.append(this._conv.normalizedName); if (!file.exists()) file.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); - if (prefs.getCharPref("purple.logging.format") == "json") + if (Services.prefs.getCharPref("purple.logging.format") == "json") this.format = "json"; file.append(getNewLogFileName(this.format)); let os = Cc["@mozilla.org/network/file-output-stream;1"]. createInstance(Ci.nsIFileOutputStream); const PR_WRITE_ONLY = 0x02; const PR_CREATE_FILE = 0x08; const PR_APPEND = 0x10; os.init(file, PR_WRITE_ONLY | PR_CREATE_FILE | PR_APPEND, 0666, 0); @@ -145,17 +130,17 @@ ConversationLog.prototype = { title: this._conv.title, account: account.normalizedName, protocol: account.protocol.normalizedName }) + "\n"; } return "Conversation with " + this._conv.name + " at " + (new Date).toLocaleString() + " on " + account.name + - " (" + account.protocol.normalizedName + ")@LINE_BREAK@"; + " (" + account.protocol.normalizedName + ")" + kLineBreak; }, _serialize: function cl_serialize(aString) { // TODO cleanup once bug 102699 is fixed let doc = getHiddenHTMLWindow().document; let div = doc.createElementNS("http://www.w3.org/1999/xhtml", "div"); div.innerHTML = aString.replace(/\r?\n/g, "
").replace(/
/gi, "
"); const type = "text/plain"; let encoder = @@ -206,17 +191,17 @@ ConversationLog.prototype = { line += sender + " : " + msg; else { if (/^\/me /.test(msg)) line += "***" + sender + " " + msg.replace(/^\/me /, ""); else line += sender + ": " + msg; } } - this._log.writeString(line + "@LINE_BREAK@"); + this._log.writeString(line + kLineBreak); }, close: function cl_close() { if (this._log) { this._log.close(); this._log = null; } } @@ -229,17 +214,17 @@ const dummyConversationLog = { var gConversationLogs = { }; function getLogForConversation(aConversation) { let id = aConversation.id; if (!(id in gConversationLogs)) { let prefName = "purple.logging.log_" + (aConversation.isChat ? "chats" : "ims"); - if (prefs.getBoolPref(prefName)) + if (Services.prefs.getBoolPref(prefName)) gConversationLogs[id] = new ConversationLog(aConversation); else gConversationLogs[id] = dummyConversationLog; } return gConversationLogs[id]; } function closeLogForConversation(aConversation) @@ -253,17 +238,17 @@ function closeLogForConversation(aConver /* System logs stuff */ function SystemLog(aAccount) { this._init(aAccount); this._log.writeString("System log for account " + aAccount.name + " (" + aAccount.protocol.normalizedName + ") connected at " + - (new Date()).toLocaleFormat("%c") + "@LINE_BREAK@"); + (new Date()).toLocaleFormat("%c") + kLineBreak); } SystemLog.prototype = { _log: null, _init: function sl_init(aAccount) { let file = getLogFolderForAccount(aAccount, true); file.append(".system"); if (!file.exists()) file.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); @@ -280,17 +265,17 @@ SystemLog.prototype = { converter.init(os, "UTF-8", 0, 0); this._log = converter; }, logEvent: function sl_logEvent(aString) { if (!this._log) this._init(); let date = (new Date()).toLocaleFormat("%x %X"); - this._log.writeString("---- " + aString + " @ " + date + " ----@LINE_BREAK@"); + this._log.writeString("---- " + aString + " @ " + date + " ----" + kLineBreak); }, close: function sl_close() { if (this._log) { this._log.close(); this._log = null; } } @@ -303,17 +288,17 @@ const dummySystemLog = { var gSystemLogs = { }; function getLogForAccount(aAccount, aCreate) { let id = aAccount.id; if (aCreate) { if (id in gSystemLogs) gSystemLogs[id].close(); - if (!prefs.getBoolPref("purple.logging.log_system")) + if (!Services.prefs.getBoolPref("purple.logging.log_system")) return dummySystemLog; return (gSystemLogs[id] = new SystemLog(aAccount)); } return (id in gSystemLogs) && gSystemLogs[id] || dummySystemLog; } function closeLogForAccount(aAccount) @@ -461,36 +446,32 @@ Logger.prototype = { getLogsForConversation: function logger_getLogsForConversation(aConversation) this._enumerateLogs(aConversation.account, aConversation.normalizedName), getSystemLogsForAccount: function logger_getSystemLogsForAccount(aAccount) this._enumerateLogs(aAccount, ".system"), observe: function logger_observe(aSubject, aTopic, aData) { switch (aTopic) { case "profile-after-change": - obs.addObserver(this, "final-ui-startup", false); + Services.obs.addObserver(this, "final-ui-startup", false); break; case "final-ui-startup": - obs.removeObserver(this, "final-ui-startup"); - ["new-conversation", "new-text", - "conversation-closed", "conversation-left-chat", + Services.obs.removeObserver(this, "final-ui-startup"); + ["new-text", "conversation-closed", "conversation-left-chat", "account-connected", "account-disconnected", "account-buddy-status-changed"].forEach(function(aEvent) { - obs.addObserver(this, aEvent, false); + Services.obs.addObserver(this, aEvent, false); }, this); break; case "new-text": if (!aSubject.noLog) { let log = getLogForConversation(aSubject.conversation); log.logMessage(aSubject); } break; - case "new-conversation": - //XXX should we create the log file here? - break; case "conversation-closed": case "conversation-left-chat": closeLogForConversation(aSubject); break; case "account-connected": getLogForAccount(aSubject, true).logEvent("+++ " + aSubject.name + " signed on"); break; diff --git a/chat/components/src/smileProtocolHandler.js b/chat/components/src/smileProtocolHandler.js --- a/chat/components/src/smileProtocolHandler.js +++ b/chat/components/src/smileProtocolHandler.js @@ -30,22 +30,22 @@ * 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 ***** */ -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource:///modules/imSmileys.jsm"); +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; -const Cc = Components.classes; -const Ci = Components.interfaces; -const smileRegexp = /^smile:\/\//; +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource:///modules/imSmileys.jsm"); + +const kSmileRegexp = /^smile:\/\//; function smileProtocolHandler() { } smileProtocolHandler.prototype = { scheme: "smile", defaultPort: -1, protocolFlags: Ci.nsIProtocolHandler.URI_NORELATIVE | Ci.nsIProtocolHandler.URI_NOAUTH | @@ -54,17 +54,17 @@ smileProtocolHandler.prototype = { newURI: function SPH_newURI(aSpec, aOriginCharset, aBaseURI) { let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI); uri.spec = aSpec; uri.QueryInterface(Ci.nsIMutable); uri.mutable = false; return uri; }, newChannel: function SPH_newChannel(aURI) { - let smile = aURI.spec.replace(smileRegexp, ""); + let smile = aURI.spec.replace(kSmileRegexp, ""); let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); let channel = ios.newChannel(getSmileRealURI(smile), null, null); channel.originalURI = aURI; return channel; }, allowPort: function SPH_allowPort(aPort, aScheme) false, classDescription: "Smile Protocol Handler", diff --git a/chat/content/browserRequest.js b/chat/content/browserRequest.js --- a/chat/content/browserRequest.js +++ b/chat/content/browserRequest.js @@ -108,18 +108,18 @@ var reporterListener = { /*in nsIRequest*/ aRequest, /*in unsigned long*/ aState) { const wpl_security_bits = wpl.STATE_IS_SECURE | wpl.STATE_IS_BROKEN | wpl.STATE_IS_INSECURE | wpl.STATE_SECURE_HIGH | wpl.STATE_SECURE_MED | wpl.STATE_SECURE_LOW; - var browser = document.getElementById("requestFrame"); - var level; + let browser = document.getElementById("requestFrame"); + let level; switch (aState & wpl_security_bits) { case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH: level = "high"; break; case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_MED: case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_LOW: level = "low"; @@ -160,17 +160,16 @@ function loadRequestedUrl() request.QueryInterface(Components.interfaces.prplIRequestBrowser); document.getElementById("headerMessage").textContent = request.promptText; let account = request.account; document.getElementById("headerLabel").value = account.protocol.name + " - " + account.name; document.getElementById("headerImage").src = account.protocol.iconBaseURI + "icon48.png"; - var browser = document.getElementById("requestFrame"); + let browser = document.getElementById("requestFrame"); browser.addProgressListener(reporterListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL); - var url = request.url; - if (url != "") { + let url = request.url; + if (url != "") browser.setAttribute("src", url); - } request.loaded(window, browser.webProgress); } diff --git a/chat/content/convbrowser.xml b/chat/content/convbrowser.xml --- a/chat/content/convbrowser.xml +++ b/chat/content/convbrowser.xml @@ -767,18 +767,18 @@ 1) return val * Math.sqrt(val) - 1; if (val < -1) return val * Math.sqrt(-val) + 1; return 0; ]]> diff --git a/chat/locales/en-US/twitter.properties b/chat/locales/en-US/twitter.properties --- a/chat/locales/en-US/twitter.properties +++ b/chat/locales/en-US/twitter.properties @@ -57,19 +57,19 @@ connection.requestTimelines=Requesting u # connection attempt. connection.error.userMismatch=Username mismatch. connection.error.failedToken=Failed to get request token. connection.error.authCancelled=You cancelled the authorization process. connection.error.authFailed=Failed to get authorization. connection.error.noNetwork=There is no network connection available. # LOCALIZATION NOTE -# This is the prompt in the browser window that pops up to authorize -# Instantbird to use a Twitter account. It is shown in the title bar of the -# authorization window. +# This is the prompt in the browser window that pops up to authorize us +# to use a Twitter account. It is shown in the title bar of the authorization +# window. authPrompt=Give permission to use your Twitter account # LOCALIZATION NOTE (options.*): # These are the protocol specific options shown in the account manager and # account wizard windows. options.track=Tracked keywords # LOCALIZATION NOTE (tooltip.*): diff --git a/chat/modules/Makefile.in b/chat/modules/Makefile.in --- a/chat/modules/Makefile.in +++ b/chat/modules/Makefile.in @@ -42,20 +42,20 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk EXTRA_JS_MODULES = \ http.jsm \ imContentSink.jsm \ imServices.jsm \ imSmileys.jsm \ imStatusUtils.jsm \ + imThemes.jsm \ imXPCOMUtils.jsm \ jsProtoHelper.jsm \ socket.jsm \ $(NULL) EXTRA_PP_JS_MODULES = \ hiddenWindow.jsm \ imTextboxUtils.jsm \ - imThemes.jsm \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/chat/modules/http.jsm b/chat/modules/http.jsm --- a/chat/modules/http.jsm +++ b/chat/modules/http.jsm @@ -32,29 +32,24 @@ * 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 ***** */ var EXPORTED_SYMBOLS = ["doXHRequest"]; -/* - TODO - replace doXHRequest with a more generic 'HTTP' object -*/ - 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) { - var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] + let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Ci.nsIXMLHttpRequest); xhr.mozBackgroundRequest = true; // no error dialogs xhr.open(aPOSTData ? "POST" : "GET", aUrl); xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS | // don't send cookies Ci.nsIChannel.LOAD_BYPASS_CACHE | Ci.nsIChannel.INHIBIT_CACHING; xhr.onerror = function(aProgressEvent) { if (aOnError) { diff --git a/chat/modules/imContentSink.jsm b/chat/modules/imContentSink.jsm --- a/chat/modules/imContentSink.jsm +++ b/chat/modules/imContentSink.jsm @@ -176,43 +176,43 @@ const kPermissiveMode = { 'font-family': true, 'font-size': true, 'font-style': true, 'font-weight': true, 'text-decoration': true } }; -const modePref = "messenger.options.filterMode"; +const kModePref = "messenger.options.filterMode"; const kModes = [kStrictMode, kStandardMode, kPermissiveMode]; var gGlobalRuleset = null; function initGlobalRuleset() { gGlobalRuleset = newRuleset(); - Services.prefs.addObserver(modePref, styleObserver, false); + Services.prefs.addObserver(kModePref, styleObserver, false); } var styleObserver = { observe: function so_observe(aObject, aTopic, aMsg) { - if (aTopic != "nsPref:changed" || aMsg != modePref) + if (aTopic != "nsPref:changed" || aMsg != kModePref) throw "bad notification"; if (!gGlobalRuleset) throw "gGlobalRuleset not initialized"; setBaseRuleset(getModePref(), gGlobalRuleset); } }; function getModePref() { - let baseNum = Services.prefs.getIntPref(modePref); + let baseNum = Services.prefs.getIntPref(kModePref); if (baseNum < 0 || baseNum > 2) baseNum = 1; return kModes[baseNum]; } function setBaseRuleset(aBase, aResult) { @@ -221,17 +221,17 @@ function setBaseRuleset(aBase, aResult) aResult.styles.__proto__ = aBase.styles; } function newRuleset(aBase) { if (!aBase) aBase = getModePref(); - var result = {}; + let result = {}; result.tags = {}; result.attrs = {}; result.styles = {}; setBaseRuleset(aBase, result); return result; } function createDerivedRuleset() @@ -265,17 +265,17 @@ function addGlobalAllowedStyleRule(aStyl } function removeGlobalAllowedStyleRule(aStyle) { delete gGlobalRuleset.styles[aStyle]; } function cleanupNode(aNode, aRules, aTextModifiers) { - for (var i = 0; i < aNode.childNodes.length; ++i) { + for (let i = 0; i < aNode.childNodes.length; ++i) { let node = aNode.childNodes[i]; if (node instanceof Components.interfaces.nsIDOMHTMLElement) { // check if node allowed let nodeName = node.localName.toLowerCase(); if (!(nodeName in aRules.tags)) { // this node is not allowed, replace it with its children while (node.hasChildNodes()) aNode.insertBefore(node.removeChild(node.firstChild), node); @@ -285,41 +285,41 @@ function cleanupNode(aNode, aRules, aTex --i; continue; } // we are going to keep this child node, clean up its children cleanupNode(node, aRules, aTextModifiers); // cleanup attributes - var attrs = node.attributes; + let attrs = node.attributes; let acceptFunction = function(aAttrRules, aAttr) { // an attribute is always accepted if its rule is true, or conditionnaly // accepted if its rule is a function that evaluates to true // if its rule does not exist, it is refused let localName = aAttr.localName; let rule = localName in aAttrRules && aAttrRules[localName]; return (rule === true || (rule instanceof Function && rule(aAttr.value))); }; - for (var j = 0; j < attrs.length; ++j) { + for (let j = 0; j < attrs.length; ++j) { let attr = attrs[j]; // we check both the list of accepted attributes for all tags // and the list of accepted attributes for this specific tag. if (!(acceptFunction(aRules.attrs, attr) || (aRules.tags[nodeName] instanceof Object) && acceptFunction(aRules.tags[nodeName], attr))) { node.removeAttribute(attr.name); --j; } } // cleanup style - var style = node.style; - for (var j = 0; j < style.length; ++j) { + let style = node.style; + for (let j = 0; j < style.length; ++j) { if (!(style[j] in aRules.styles)) { style.removeProperty(style[j]); --j; } } } else { // We are on a text node, we need to apply the functions @@ -331,19 +331,19 @@ function cleanupNode(aNode, aRules, aTex // * positive value if nodes were added. // For instance, adding an tag for a smiley adds 2 nodes: // - the img tag // - the new text node after the img tag. // This is the number of nodes we need to process. If new nodes // are created, the next text modifier functions have more nodes // to process. - var textNodeCount = 1; - for each (var modifier in aTextModifiers) - for (var n = 0; n < textNodeCount; ++n) { + let textNodeCount = 1; + for each (let modifier in aTextModifiers) + for (let n = 0; n < textNodeCount; ++n) { let textNode = aNode.childNodes[i + n]; // If we are processing nodes created by one of the previous // text modifier function, some of the nodes are likely not // text node, skip them. if (!(textNode instanceof Components.interfaces.nsIDOMText)) continue; @@ -361,13 +361,13 @@ function cleanupNode(aNode, aRules, aTex function cleanupImMarkup(aDocument, aText, aRuleset, aTextModifiers) { if (!aDocument) throw "providing an HTML document is required"; if (!gGlobalRuleset) initGlobalRuleset(); - var div = aDocument.createElement("div"); + let div = aDocument.createElement("div"); div.innerHTML = aText; cleanupNode(div, aRuleset || gGlobalRuleset, aTextModifiers || []); return div.innerHTML; } diff --git a/chat/modules/imSmileys.jsm b/chat/modules/imSmileys.jsm --- a/chat/modules/imSmileys.jsm +++ b/chat/modules/imSmileys.jsm @@ -40,32 +40,32 @@ Components.utils.import("resource:///mod var EXPORTED_SYMBOLS = [ "smileImMarkup", // used to add smile:// img tags into IM markup. "smileTextNode", // used to add smile:// img tags to the content of a textnode "smileString", // used to add smile:// img tags into a string without parsing it as HTML. Be sure the string doesn't contain HTML tags. "getSmileRealURI", // used to retrive the chrome URI for a smile:// URI "getSmileyList" // used to display a list of smileys in the UI ]; -const emoticonsThemePref = "messenger.options.emoticonsTheme"; -const themeFile = "theme.js"; +const kEmoticonsThemePref = "messenger.options.emoticonsTheme"; +const kThemeFile = "theme.js"; __defineGetter__("gTheme", function() { delete this.gTheme; gPrefObserver.init(); return this.gTheme = getTheme(); }); var gPrefObserver = { init: function po_init() { - Services.prefs.addObserver(emoticonsThemePref, gPrefObserver, false); + Services.prefs.addObserver(kEmoticonsThemePref, gPrefObserver, false); }, observe: function so_observe(aObject, aTopic, aMsg) { - if (aTopic != "nsPref:changed" || aMsg != emoticonsThemePref) + if (aTopic != "nsPref:changed" || aMsg != kEmoticonsThemePref) throw "bad notification"; gTheme = getTheme(); } }; function getSmileRealURI(aSmile) { @@ -89,34 +89,34 @@ function getSmileyList(aThemeName) src: theme.baseUri + aSmiley.filename, textCodes: aSmiley.textCodes}; }; return theme.json.smileys.map(addAbsoluteUrls); } function getTheme(aName) { - let name = aName || Services.prefs.getCharPref(emoticonsThemePref); + let name = aName || Services.prefs.getCharPref(kEmoticonsThemePref); let theme = { name: name, iconsHash: null, json: null, regExp: null }; if (name == "none") return theme; if (name == "default") theme.baseUri = "chrome://instantbird-emoticons/skin/"; else theme.baseUri = "chrome://" + theme.name + "/skin/"; try { - let channel = Services.io.newChannel(theme.baseUri + themeFile, null, null); + let channel = Services.io.newChannel(theme.baseUri + kThemeFile, null, null); let stream = channel.open(); let json = Components.classes["@mozilla.org/dom/json;1"] .createInstance(Components.interfaces.nsIJSON); theme.json = json.decodeFromStream(stream, stream.available()); stream.close(); theme.iconsHash = {}; for each (let smiley in theme.json.smileys) { for each (let textCode in smiley.textCodes) @@ -164,20 +164,20 @@ function getRegexp() gTheme.regExp = new RegExp('(' + emoticonList.join('|') + ')', 'g'); return gTheme.regExp; } // unused. May be useful later to process a string instead of an HTML node function smileString(aString) { - const smileFormat = '$1'; + const kSmileFormat = '$1'; let exp = getRegexp(); - return exp ? aString.replace(exp, smileFormat) : aString; + return exp ? aString.replace(exp, kSmileFormat) : aString; } function smileTextNode(aNode) { /* * Skip text nodes that contain the href in the child text node. * We must check both the testNode.textContent and the aNode.data since they * cover different cases: @@ -216,17 +216,17 @@ function smileTextNode(aNode) result += 2; exp.lastIndex = 0; } return result; } function smileNode(aNode) { - for (var i = 0; i < aNode.childNodes.length; ++i) { + for (let i = 0; i < aNode.childNodes.length; ++i) { let node = aNode.childNodes[i]; if (node instanceof Components.interfaces.nsIDOMHTMLElement) { // we are on a tag, recurse to process its children smileNode(node); } else if (node instanceof Components.interfaces.nsIDOMText) { // we are on a text node, process it smileTextNode(node); } @@ -237,13 +237,13 @@ function smileImMarkup(aDocument, aText) { if (!aDocument) throw "providing an HTML document is required"; // return early if smileys are disabled if (!gTheme.iconsHash) return aText; - var div = aDocument.createElement("div"); + let div = aDocument.createElement("div"); div.innerHTML = aText; smileNode(div); return div.innerHTML; } diff --git a/chat/modules/imThemes.jsm b/chat/modules/imThemes.jsm --- a/chat/modules/imThemes.jsm +++ b/chat/modules/imThemes.jsm @@ -30,52 +30,48 @@ * 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 ***** */ -#filter substitution -#ifdef XP_WIN -#define LINE_BREAK \r\n -#else -#define LINE_BREAK \n -#endif - var EXPORTED_SYMBOLS = [ "getCurrentTheme", "getThemeByName", "getHTMLForMessage", "getThemeVariants", "isNextMessage", "insertHTMLForMessage", "initHTMLDocument", "getMessagesForRange", "serializeSelection" ]; -Components.utils.import("resource:///modules/imServices.jsm"); -Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); -const Ci = Components.interfaces; +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; -const messagesStylePrefBranch = "messenger.options.messagesStyle."; -const themePref = "theme"; -const variantPref = "variant"; -const showHeaderPref = "showHeader"; -const combineConsecutivePref = "combineConsecutive"; -const combineConsecutiveIntervalPref = "combineConsecutiveInterval"; +Cu.import("resource:///modules/imServices.jsm"); +Cu.import("resource://gre/modules/DownloadUtils.jsm"); + +const kMessagesStylePrefBranch = "messenger.options.messagesStyle."; +const kThemePref = "theme"; +const kVariantPref = "variant"; +const kShowHeaderPref = "showHeader"; +const kCombineConsecutivePref = "combineConsecutive"; +const kCombineConsecutiveIntervalPref = "combineConsecutiveInterval"; const DEFAULT_THEME = "bubbles"; const DEFAULT_THEMES = ["bubbles", "dark", "papersheets", "simple"]; +const kLineBreak = "@mozilla.org/windows-registry-key;1" in Cc ? "\r\n" : "\n"; + __defineGetter__("gPrefBranch", function() { delete this.gPrefBranch; - return this.gPrefBranch = Services.prefs.getBranch(messagesStylePrefBranch); + return this.gPrefBranch = Services.prefs.getBranch(kMessagesStylePrefBranch); }); var gCurrentTheme = null; function getChromeFile(aURI) { try { let channel = Services.io.newChannel(aURI, null, null); @@ -221,26 +217,26 @@ function getThemeByName(aName) throw "Cannot load theme " + aName; return { name: aName, variant: "default", baseURI: baseURI, metadata: metadata, html: new HTMLTheme(baseURI), - showHeader: gPrefBranch.getBoolPref(showHeaderPref), - combineConsecutive: gPrefBranch.getBoolPref(combineConsecutivePref), - combineConsecutiveInterval: gPrefBranch.getIntPref(combineConsecutiveIntervalPref) + showHeader: gPrefBranch.getBoolPref(kShowHeaderPref), + combineConsecutive: gPrefBranch.getBoolPref(kCombineConsecutivePref), + combineConsecutiveInterval: gPrefBranch.getIntPref(kCombineConsecutiveIntervalPref) }; } function getCurrentTheme() { - let name = gPrefBranch.getCharPref(themePref); - let variant = gPrefBranch.getCharPref(variantPref); + let name = gPrefBranch.getCharPref(kThemePref); + let variant = gPrefBranch.getCharPref(kVariantPref); if (gCurrentTheme && gCurrentTheme.name == name && gCurrentTheme.variant == variant) return gCurrentTheme; try { gCurrentTheme = getThemeByName(name); gCurrentTheme.variant = variant; } catch(e) { @@ -263,17 +259,17 @@ function getDirectoryEntries(aDir) // remove any trailing file name added by convertChromeURL let spec = uri.spec.replace(/[^\/]+$/, ""); uri = ios.newURI(spec, null, null); let results = []; if (uri.scheme == "jar") { uri.QueryInterface(Ci.nsIJARURI); - var strEntry = uri.JAREntry; + let strEntry = uri.JAREntry; if (!strEntry) return []; let zr = Components.classes["@mozilla.org/libjar/zip-reader;1"] .createInstance(Ci.nsIZipReader); let jarFile = uri.JARFile; if (jarFile instanceof Ci.nsIJARURI) { let innerZr = Components.classes["@mozilla.org/libjar/zip-reader;1"] @@ -284,28 +280,28 @@ function getDirectoryEntries(aDir) else zr.open(jarFile.QueryInterface(Ci.nsIFileURL).file); if (!zr.hasEntry(strEntry) || !zr.getEntry(strEntry).isDirectory) { zr.close(); return []; } - var escapedEntry = strEntry.replace(/([*?$[\]^~()\\])/g, "\\$1"); - var filter = escapedEntry + "?*~" + escapedEntry + "?*/?*"; - var entries = zr.findEntries(filter); + let escapedEntry = strEntry.replace(/([*?$[\]^~()\\])/g, "\\$1"); + let filter = escapedEntry + "?*~" + escapedEntry + "?*/?*"; + let entries = zr.findEntries(filter); let parentLength = strEntry.length; while (entries.hasMore()) results.push(entries.getNext().substring(parentLength)); zr.close(); } else if (uri.scheme == "file") { uri.QueryInterface(Ci.nsIFileURL); - var dir = uri.file; + let dir = uri.file; if (!dir.exists() || !dir.isDirectory()) return []; let children = dir.directoryEntries; while (children.hasMoreElements()) { let file = children.getNext() .QueryInterface(Ci.nsIFile); @@ -315,19 +311,18 @@ function getDirectoryEntries(aDir) return results; } function getThemeVariants(aTheme) { let variants = getDirectoryEntries(aTheme.baseURI + "Variants/"); let cssRe = /\.css$/; - variants = variants.filter(function(v) cssRe.test(v)) - .map(function(v) v.replace(cssRe, "")); - return variants; + return variants.filter(function(v) cssRe.test(v)) + .map(function(v) v.replace(cssRe, "")); } /* helper function for replacements in messages */ function getBuddyFromMessage(aMsg) { if (aMsg.incoming) { let conv = aMsg.conversation; if (!conv.isChat) @@ -355,17 +350,17 @@ function getStatusIconFromBuddy(aBuddy) } const headerFooterReplacements = { chatName: function(aConv) aConv.title, sourceName: function(aConv) aConv.account.alias || aConv.account.name, destinationName: function(aConv) aConv.name, destinationDisplayName: function(aConv) aConv.title, incomingIconPath: function(aConv) { - var buddy; + let buddy; return (!aConv.isChat && (buddy = aConv.buddy) && buddy.buddyIconFilename) || "incoming_icon.png"; }, outgoingIconPath: function(aConv) "outgoing_icon.png", timeOpened: function(aConv, aFormat) { if (aFormat) return (new Date()).toLocaleFormat(aFormat); else @@ -460,33 +455,33 @@ const statusReplacements = { let buddy = null; if (!conv.isChat) buddy = conv.buddy; return getStatusIconFromBuddy(buddy); }, __proto__: statusMessageReplacements }; -const replacementRegExp = /%([a-zA-Z]*)(\{([^\}]*)\})?%/g; +const kReplacementRegExp = /%([a-zA-Z]*)(\{([^\}]*)\})?%/g; function replaceKeywordsInHTML(aHTML, aReplacements, aReplacementArg) { - replacementRegExp.lastIndex = 0; + kReplacementRegExp.lastIndex = 0; let previousIndex = 0; let result = ""; let match; - while ((match = replacementRegExp.exec(aHTML))) { + while ((match = kReplacementRegExp.exec(aHTML))) { let content = ""; if (match[1] in aReplacements) content = aReplacements[match[1]](aReplacementArg, match[3]); else Components.utils.reportError("Unknown replacement string %" + match[1] + "% in message styles."); result += aHTML.substring(previousIndex, match.index) + content; - previousIndex = replacementRegExp.lastIndex; + previousIndex = kReplacementRegExp.lastIndex; } return result + aHTML.slice(previousIndex); } function isNextMessage(aTheme, aMsg, aPreviousMsg) { if (!aTheme.combineConsecutive || @@ -587,17 +582,17 @@ function getMetadata(aTheme, aKey) ((aKey + ":" + aTheme.metadata.DefaultVariant) in aTheme.metadata)) return aTheme.metadata[aKey + ":" + aTheme.metadata.DefaultVariant]; return aTheme.metadata[aKey]; } function initHTMLDocument(aConv, aTheme, aDoc) { - var HTML = ""; + let HTML = ""; function addCSS(aHref) { HTML += ""; } addCSS("chrome://chat/skin/conv.css"); // add css to handle DefaultFontFamily and DefaultFontSize @@ -647,18 +642,21 @@ function getEllipsis() .getComplexValue("messenger.conversations.selections.ellipsis", Ci.nsIPrefLocalizedString).data; } catch (e) { } return ellipsis; } function _serializeDOMObject(aDocument, aInitFunction) { - const type = "text/plain"; - var encoder = + // This shouldn't really be a constant, as we want to support + // text/html too in the future. + const type = "text/plain"; + + let encoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=" + type] .createInstance(Ci.nsIDocumentEncoder); encoder.init(aDocument, type, 0); aInitFunction(encoder); let result = encoder.encodeToString(); return result; } @@ -672,39 +670,39 @@ function serializeNode(aNode) { return _serializeDOMObject(aNode.ownerDocument, function(aEncoder) { aEncoder.setNode(aNode); }); } /* This function is used to pretty print a selection inside a conversation area */ function serializeSelection(aSelection) { - // We have to kinds of selection serialization: + // We have two kinds of selection serialization: // - The short version, used when only a part of message is // selected, or if nothing interesting is selected - var shortSelection = ""; + let shortSelection = ""; // - The long version, which is used: // * when both some of the message text and some of the context // (sender, time, ...) is selected; // * when several messages are selected at once // This version uses an array, with each message formatted // through the theme system. - var longSelection = []; + let longSelection = []; // We first assume that we are going to use the short version, but // while working on creating the short version, we prepare // everything to be able to switch to the long version if we later // discover that it is in fact needed. - var shortVersionPossible = true; + let shortVersionPossible = true; // Sometimes we need to know if a selection range is inside the same // message as the previous selection range, so we keep track of the // last message we have processed. - var lastMessage = null; + let lastMessage = null; for (let i = 0; i < aSelection.rangeCount; ++i) { let range = aSelection.getRangeAt(i); let messages = getMessagesForRange(range); // If at least one selected message has some of its text selected, // remove from the selection all the messages that have no text // selected @@ -723,17 +721,17 @@ function serializeSelection(aSelection) (!messages[0].isTextSelected() || messages[0].onlyTextSelected()) && (!lastMessage || lastMessage.msg == messages[0].msg || lastMessage.msg.who == messages[0].msg.who)) { if (shortSelection) { if (lastMessage.msg != messages[0].msg) { // Add the ellipsis only if the previous message was cut if (lastMessage.cutEnd) shortSelection += " " + getEllipsis(); - shortSelection += "@LINE_BREAK@"; + shortSelection += kLineBreak; } else shortSelection += " " + getEllipsis() + " "; } shortSelection += serializeRange(range); longSelection.push(messages[0].getFormattedMessage()); } else { @@ -751,17 +749,17 @@ function serializeSelection(aSelection) } } lastMessage = messages[messages.length - 1]; } if (shortVersionPossible) return shortSelection || aSelection.toString(); else - return longSelection.join("@LINE_BREAK@"); + return longSelection.join(kLineBreak); } function SelectedMessage(aRootNode, aRange) { this._rootNodes = [aRootNode]; this._range = aRange; } @@ -847,17 +845,17 @@ SelectedMessage.prototype = { } else this._cutBegin = false; if (endPoint == 1) { let range = spanNode.ownerDocument.createRange(); range.setStart(this._range.endContainer, this._range.endOffset); range.setEnd(spanNode, spanNode.childNodes.length); - this._cutEnd = !/^(@LINE_BREAK@)?$/.test(serializeRange(range)); + this._cutEnd = !/^(\r?\n)?$/.test(serializeRange(range)); } else this._cutEnd = false; } this._otherSelected = (startPoint >= 0 || endPoint <= 0) && // eliminate most negative cases (!this._textSelected || serializeRange(this._range).length > this._selectedText.length); diff --git a/chat/modules/imXPCOMUtils.jsm b/chat/modules/imXPCOMUtils.jsm --- a/chat/modules/imXPCOMUtils.jsm +++ b/chat/modules/imXPCOMUtils.jsm @@ -96,21 +96,21 @@ function initLogModule(aModule, aThis) aThis.DEBUG = scriptError.bind(aThis, aModule, DEBUG_MISC); aThis.LOG = scriptError.bind(aThis, aModule, DEBUG_INFO); aThis.WARN = scriptError.bind(aThis, aModule, DEBUG_WARNING); aThis.ERROR = scriptError.bind(aThis, aModule, DEBUG_ERROR); } function setTimeout(aFunction, aDelay) { - var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - var args = Array.prototype.slice.call(arguments, 2); + let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + let args = Array.prototype.slice.call(arguments, 2); // A reference to the timer should be kept to ensure it won't be // GC'ed before firing the callback. - var callback = { + let callback = { _timer: timer, notify: function (aTimer) { aFunction.apply(null, args); delete this._timer; } }; timer.initWithCallback(callback, aDelay, Ci.nsITimer.TYPE_ONE_SHOT); return timer; } function clearTimeout(aTimer) { @@ -150,17 +150,17 @@ ClassInfo.prototype = { QueryInterface: function ClassInfo_QueryInterface(iid) { if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsIClassInfo) || this._interfaces.some(function(i) i.equals(iid))) return this; throw Cr.NS_ERROR_NO_INTERFACE; }, getInterfaces: function(countRef) { - var interfaces = + let interfaces = [Ci.nsIClassInfo, Ci.nsISupports].concat(this._interfaces); countRef.value = interfaces.length; return interfaces; }, getHelperForLanguage: function(language) null, contractID: null, classID: null, implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT, diff --git a/chat/modules/jsProtoHelper.jsm b/chat/modules/jsProtoHelper.jsm --- a/chat/modules/jsProtoHelper.jsm +++ b/chat/modules/jsProtoHelper.jsm @@ -325,17 +325,17 @@ const GenericAccountBuddyPrototype = { get availabilityDetails() this._availabilityDetails, get canSendMessage() this.online /*|| this.account.canSendOfflineMessage(this) */, getTooltipInfo: function() EmptyEnumerator, createConversation: function() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; } }; -// aUserName is required only if aBuddy is null (= we are adding a buddy) +// aUserName is required only if aBuddy is null, i.e., we are adding a buddy. function AccountBuddy(aAccount, aBuddy, aTag, aUserName) { this._init(aAccount, aBuddy, aTag, aUserName); } AccountBuddy.prototype = GenericAccountBuddyPrototype; const GenericMessagePrototype = { __proto__: ClassInfo("prplIMessage", "generic message object"), flags: Ci.nsIClassInfo.DOM_OBJECT, @@ -575,18 +575,18 @@ TooltipInfo.prototype = ClassInfo("prplI function purplePref(aName, aOption) { this.name = aName; // Preference name this.label = aOption.label; // Text to display if (aOption.default === undefined || aOption.default === null) throw "A default value for the option is required to determine its type."; this._defaultValue = aOption.default; - const types = {boolean: "Bool", string: "String", number: "Int"}; - let type = types[typeof aOption.default]; + const kTypes = {boolean: "Bool", string: "String", number: "Int"}; + let type = kTypes[typeof aOption.default]; if (!type) throw "Invalid option type"; if (type == "String" && ("listValues" in aOption)) { type = "List"; this._listValues = aOption.listValues; } this.type = Ci.prplIPref["type" + type]; diff --git a/chat/modules/socket.jsm b/chat/modules/socket.jsm --- a/chat/modules/socket.jsm +++ b/chat/modules/socket.jsm @@ -380,16 +380,17 @@ const Socket = { else this.onConnectionClosed(); }, /* * nsIBadCertListener2 */ // Called when there's an error, return true to suppress the modal alert. + // Whatever this function returns, NSS will close the connection. notifyCertProblem: function(aSocketInfo, aStatus, aTargetSite) true, /* * nsISSLErrorListener */ notifySSLError: function(aSocketInfo, aError, aTargetSite) true, /* diff --git a/chat/protocols/twitter/twitter.js b/chat/protocols/twitter/twitter.js --- a/chat/protocols/twitter/twitter.js +++ b/chat/protocols/twitter/twitter.js @@ -304,19 +304,19 @@ Conversation.prototype = { str: "@" + um.screen_name, title: um.name, href: "https://twitter.com/" + um.screen_name}))); } entArray.sort(function(a, b) a.start - b.start); let offset = 0; for each (let entity in entArray) { let str = text.substring(offset + entity.start, offset + entity.end); - if (str[0] == "@") + if (str[0] == "\uFF20") // @ - unicode character similar to @ str = "@" + str.substring(1); - if (str[0] == "#") + if (str[0] == "\uFF03") // # - unicode character similar to # str = "#" + str.substring(1); if (str.toLowerCase() != entity.str.toLowerCase()) continue; let html = ""; @@ -412,22 +412,22 @@ Account.prototype = { }, // Twitter doesn't broadcast the user's availability, so we can ignore // imIUserStatusInfo's status notifications. observe: function(aSubject, aTopic, aMsg) { }, signAndSend: function(aUrl, aHeaders, aPOSTData, aOnLoad, aOnError, aThis, aOAuthParams) { - const chars = + const kChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; - const nonceLength = 6; + const kNonceLength = 6; let nonce = ""; - for (var i = 0; i < nonceLength; ++i) - nonce += chars[Math.floor(Math.random() * chars.length)]; + for (let i = 0; i < kNonceLength; ++i) + nonce += kChars[Math.floor(Math.random() * kChars.length)]; let params = (aOAuthParams || []).concat([ ["oauth_consumer_key", this.consumerKey], ["oauth_nonce", nonce], ["oauth_signature_method", "HMAC-SHA1"], ["oauth_token", this.token], ["oauth_timestamp", Math.floor(((new Date()).getTime()) / 1000)], ["oauth_version", "1.0"] @@ -783,17 +783,17 @@ Account.prototype = { } this.token = data.oauth_token; this.tokenSecret = data.oauth_token_secret; this.requestAuthorization(); }, requestAuthorization: function() { this.reportConnecting(_("connection.requestAuth")); - const url = this.baseURI + "oauth/authorize?oauth_token="; + let url = this.baseURI + "oauth/authorize?oauth_token="; this._browserRequest = { get promptText() _("authPrompt"), account: this, url: url + this.token, _active: true, cancelled: function() { if (!this._active) return; @@ -957,17 +957,17 @@ Account.prototype = { } let userInfo = this._userInfo[aBuddyName]; // List of the names of the info to actually show in the tooltip and // optionally a transform function to apply to the value. // See https://dev.twitter.com/docs/api/1/get/users/show for the options. let normalizeBool = function(isFollowing) _(isFollowing ? "yes" : "no"); - const fields = { + const kFields = { following: normalizeBool, description: null, url: null, location: null, lang: function(aLang) { try { return _lang(aLang); } @@ -980,21 +980,21 @@ Account.prototype = { created_at: function(aDate) (new Date(aDate)).toLocaleDateString(), statuses_count: null, friends_count: null, followers_count: null, listed_count: null }; let tooltipInfo = []; - for (let field in fields) { + for (let field in kFields) { if (hasOwnProperty(userInfo, field) && userInfo[field]) { let value = userInfo[field]; - if (fields[field]) - value = fields[field](value); + if (kFields[field]) + value = kFields[field](value); tooltipInfo.push(new TooltipInfo(_("tooltip." + field), value)); } } Services.obs.notifyObservers(new nsSimpleEnumerator(tooltipInfo), "user-info-received", aBuddyName); }, diff --git a/chat/protocols/xmpp/xmpp-authmechs.jsm b/chat/protocols/xmpp/xmpp-authmechs.jsm --- a/chat/protocols/xmpp/xmpp-authmechs.jsm +++ b/chat/protocols/xmpp/xmpp-authmechs.jsm @@ -122,22 +122,22 @@ DigestMD5Auth.prototype = { if (e.length != 2) throw "Error decoding: " + elem; data[e[0]] = e[1].replace(/"|'/g, ""); } data.username = this._username; - const chars = + const kChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; - const nonceLength = 32; + const kNonceLength = 32; let nonce = ""; - for (let i = 0; i < nonceLength; ++i) - nonce += chars[Math.floor(Math.random() * chars.length)]; + for (let i = 0; i < kNonceLength; ++i) + nonce += kChars[Math.floor(Math.random() * kChars.length)]; data.cnonce = nonce; data.nc = "00000001"; data.qop = "auth", data["digest-uri"] = "xmpp/" + this._domain + (data.host ? "/" + host : ""); data.response = digestMD5(this._username, data.realm, this._password, data.nonce, data.cnonce, data["digest-uri"]); data.charset = "utf-8"; diff --git a/chat/protocols/xmpp/xmpp-session.jsm b/chat/protocols/xmpp/xmpp-session.jsm --- a/chat/protocols/xmpp/xmpp-session.jsm +++ b/chat/protocols/xmpp/xmpp-session.jsm @@ -32,18 +32,17 @@ * 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 ***** */ var EXPORTED_SYMBOLS = ["XMPPSession", "XMPPDefaultResource"]; -const Cu = Components.utils; -const Ci = Components.interfaces; +const {interfaces: Ci, utils: Cu} = Components; Cu.import("resource:///modules/imXPCOMUtils.jsm"); Cu.import("resource:///modules/socket.jsm"); Cu.import("resource:///modules/xmpp-xml.jsm"); Cu.import("resource:///modules/xmpp-authmechs.jsm"); initLogModule("xmpp-session", this); @@ -324,29 +323,29 @@ XMPPSession.prototype = { let errorMsg = "authenticationFailure"; if (aStanza.getElement(["not-authorized"])) errorMsg = "notAuthorized"; this.onError(Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED, _("connection.error." + errorMsg)); return; } - let rv; + let result; try { - rv = this._auth.next(aStanza); + result = this._auth.next(aStanza); } catch(e) { ERROR(e); this.onError(Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED, _("connection.error.authenticationFailure")); return; } - if (rv.send) - this.send(rv.send.getXML()); - if (rv.done) + if (result.send) + this.send(result.send.getXML()); + if (result.done) this.onXmppStanza = this.stanzaListeners.authResult; }, authResult: function(aStanza) { if (aStanza.localName != "success") { this.onError(Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED, _("connection.error.notAuthorized")); return; } diff --git a/chat/protocols/xmpp/xmpp.jsm b/chat/protocols/xmpp/xmpp.jsm --- a/chat/protocols/xmpp/xmpp.jsm +++ b/chat/protocols/xmpp/xmpp.jsm @@ -111,16 +111,17 @@ MUCParticipant.prototype = { get noFlags() this.role < kRoles.indexOf("member"), get voiced() this.role == kRoles.indexOf("member"), get halfOp() this.role == kRoles.indexOf("moderator"), get op() this.role == kRoles.indexOf("admin"), get founder() this.role == kRoles.indexOf("owner"), typing: false }; +// MUC (Multi-User Chat) const XMPPMUCConversationPrototype = { __proto__: GenericConvChatPrototype, _init: function(aAccount, aJID, aNick) { GenericConvChatPrototype._init.call(this, aAccount, aJID, aNick); }, get normalizedName() this.name, @@ -353,27 +354,27 @@ const XMPPAccountBuddyPrototype = { }, get normalizedName() this.userName, /* Display name of the buddy */ get contactDisplayName() this.buddy.contact.displayName || this.displayName, _saveIcon: function(aPhotoNode) { let type = aPhotoNode.getElement(["TYPE"]).innerText; - const ext = {"image/gif": "gif", "image/jpeg": "jpg", "image/png": "png"}; - if (!ext.hasOwnProperty(type)) + const kExt = {"image/gif": "gif", "image/jpeg": "jpg", "image/png": "png"}; + if (!kExt.hasOwnProperty(type)) return; let data = aPhotoNode.getElement(["BINVAL"]).innerText; let content = atob(data.replace(/[^A-Za-z0-9\+\/\=]/g, "")); let istream = Cc["@mozilla.org/io/string-input-stream;1"] .createInstance(Ci.nsIStringInputStream); istream.setData(content, content.length); - let fileName = this.normalizedName + "." + ext[type]; + let fileName = this.normalizedName + "." + kExt[type]; let file = FileUtils.getFile("ProfD", ["icons", this.account.protocol.normalizedName, this.account.normalizedName, fileName]); let ostream = FileUtils.openSafeFileOutputStream(file); let buddy = this; NetUtil.asyncCopy(istream, ostream, function(rc) { if (Components.isSuccessCode(rc))