Bug 955420 - Default normalizedName normalization is too aggressive, r=clokep.
authoraleth <aleth@instantbird.org>
Sat, 09 Nov 2013 22:16:16 -0500
changeset 19230 667a503cf3a145480f3b7b91b56efea404200e8e
parent 19229 74405c5aecb2928bb7cce03517a76f446847acef
child 19231 76743075c40f0c81787f58647b220ea7f5a207ff
push id1103
push usermbanner@mozilla.com
push dateTue, 18 Mar 2014 07:44:06 +0000
treeherdercomm-beta@50c6279a0af0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersclokep
bugs955420
Bug 955420 - Default normalizedName normalization is too aggressive, r=clokep.
chat/modules/jsProtoHelper.jsm
chat/protocols/twitter/twitter.js
--- a/chat/modules/jsProtoHelper.jsm
+++ b/chat/modules/jsProtoHelper.jsm
@@ -18,18 +18,16 @@ const {classes: Cc, interfaces: Ci, resu
 
 Cu.import("resource:///modules/imXPCOMUtils.jsm");
 Cu.import("resource:///modules/imServices.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "_", function()
   l10nHelper("chrome://chat/locale/conversations.properties")
 );
 
-function normalize(aString) aString.replace(/[^a-z0-9]/gi, "").toLowerCase()
-
 const GenericAccountPrototype = {
   __proto__: ClassInfo("prplIAccount", "generic account object"),
   get wrappedJSObject() this,
   _init: function _init(aProtocol, aImAccount) {
     this.protocol = aProtocol;
     this.imAccount = aImAccount;
     initLogModule(aProtocol.id, this);
   },
@@ -210,17 +208,17 @@ const GenericAccountPrototype = {
              this.prefs.getComplexValue(aName, Ci.nsISupportsString).data :
              this.protocol._getOptionDefault(aName);
   },
 
   get prefs() this._prefs ||
     (this._prefs = Services.prefs.getBranch("messenger.account." +
                                             this.imAccount.id + ".options.")),
 
-  get normalizedName() normalize(this.name),
+  get normalizedName() this.name.toLowerCase(),
   get proxyInfo() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
   set proxyInfo(val) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
 
   get HTMLEnabled() false,
   get HTMLEscapePlainText() false,
   get noBackgroundColors() true,
   get autoResponses() false,
   get singleFormatting() false,
@@ -277,17 +275,17 @@ const GenericAccountBuddyPrototype = {
     } catch(e) {
       this.ERROR(e);
     }
   },
 
   _userName: "",
   get userName() this._userName || this._buddy.userName,
   get normalizedName()
-    this._userName ? normalize(this._userName) : this._buddy.normalizedName,
+    this._userName ? this._userName.toLowerCase() : this._buddy.normalizedName,
   _serverAlias: "",
   get serverAlias() this._serverAlias,
   set serverAlias(aNewAlias) {
     let old = this.displayName;
     this._serverAlias = aNewAlias;
     if (old != this.displayName)
       this._notifyObservers("display-name-changed", old);
   },
@@ -490,17 +488,17 @@ const GenericConversationPrototype = {
   },
 
   writeMessage: function(aWho, aText, aProperties) {
     (new Message(aWho, aText, aProperties)).conversation = this;
   },
 
   get account() this._account.imAccount,
   get name() this._name,
-  get normalizedName() normalize(this.name),
+  get normalizedName() this.name.toLowerCase(),
   get title() this.name,
   get startDate() this._date
 };
 
 const GenericConvIMPrototype = {
   __proto__: GenericConversationPrototype,
   _interfaces: [Ci.prplIConversation, Ci.prplIConvIM],
   classDescription: "generic ConvIM object",
@@ -751,17 +749,17 @@ ChatRoomFieldValues.prototype = {
 const GenericProtocolPrototype = {
   __proto__: ClassInfo("prplIProtocol", "Generic protocol object"),
 
   init: function(aId) {
     if (aId != this.id)
       throw "Creating an instance of " + aId + " but this object implements " + this.id;
   },
   get id() "prpl-" + this.normalizedName,
-  get normalizedName() normalize(this.name),
+  get normalizedName() this.name.toLowerCase(),
   get iconBaseURI() "chrome://chat/skin/prpl-generic/",
 
   getAccount: function(aImAccount) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
 
   _getOptionDefault: function(aName) {
     if (this.options && this.options.hasOwnProperty(aName))
       return this.options[aName].default;
     throw aName + " has no default value in " + this.id + ".";
--- a/chat/protocols/twitter/twitter.js
+++ b/chat/protocols/twitter/twitter.js
@@ -124,16 +124,17 @@ function Conversation(aAccount)
   if (aAccount._userInfo.has(aAccount.name)) {
     let userInfo = aAccount._userInfo.get(aAccount.name);
     if ("description" in userInfo)
       this.setTopic(userInfo.description, aAccount.name, true);
   }
 }
 Conversation.prototype = {
   __proto__: GenericConvChatPrototype,
+  get normalizedName() this._account.normalize(this.name),
   unInit: function() {
     delete this._account._timeline;
     GenericConvChatPrototype.unInit.call(this);
   },
   inReplyToStatusId: null,
   startReply: function(aTweet) {
     this.inReplyToStatusId = aTweet.id_str;
     let entities = aTweet.entities;
@@ -365,16 +366,21 @@ function Account(aProtocol, aImAccount)
 {
   this._init(aProtocol, aImAccount);
   this._knownMessageIds = new Set();
   this._userInfo = new Map();
   this._friends = new Set();
 }
 Account.prototype = {
   __proto__: GenericAccountPrototype,
+  // The correct normalization for twitter would be just toLowerCase().
+  // Unfortunately, for backwards compatibility we retain this normalization,
+  // which can cause edge cases for usernames with underscores.
+  normalize: function(aString) aString.replace(/[^a-z0-9]/gi, "").toLowerCase(),
+  get normalizedName() this.normalize(this.name),
 
   consumerKey: Services.prefs.getCharPref("chat.twitter.consumerKey"),
   consumerSecret: Services.prefs.getCharPref("chat.twitter.consumerSecret"),
   completionURI: "http://oauthcallback.local/",
   baseURI: "https://api.twitter.com/",
   _lastMsgId: "",
 
   // Use this to keep track of the pending timeline requests. We attempt to fetch