Bug 1138689 - /me and /action should fire a sending-message notification before actually sending the action. r=clokep
authorArlo Breault <arlolra@gmail.com>
Fri, 13 Mar 2015 13:04:26 -0700
changeset 22685 1bf87d31938fd6e6e64b5a78aaaf17c6c0f25a07
parent 22684 68f9b79c4fa70d7daade2831d79df1302b9c996b
child 22686 ee0620ac1185699823a4665e732b22b96c8c0071
push idunknown
push userunknown
push dateunknown
reviewersclokep
bugs1138689
Bug 1138689 - /me and /action should fire a sending-message notification before actually sending the action. r=clokep
AUTHORS
chat/components/public/imIConversationsService.idl
chat/components/src/imConversations.js
chat/protocols/irc/ircCommands.jsm
--- a/AUTHORS
+++ b/AUTHORS
@@ -25,16 +25,17 @@ alta88 <alta88@gmail.com>
 Andreas Nilsson <nisses.mail@home.se>
 Andrew Sutherland <asutherland@asutherland.org>
 Andrew Wooldridge <andreww@netscape.com>
 Andrey Terentyev <andreycpp@gmail.com>
 Anirvana Mishra <anidps@gmail.com>
 Annie Sullivan <annie.sullivan@gmail.com>
 Archaeopteryx <archaeopteryx@coole-files.de>
 ArentJan Banck <ajbanck@planet.nl>
+Arlo Breault <arlolra@gmail.com>
 Arthur Wiebe <artooro@gmail.com>
 Asaf Romano <mano@mozilla.com>
 Atul Varma <atul@mozilla.com>
 ause <ause@sun.com>
 Axel Zechner <axel.zechner@googlemail.com>
 Baki Bon <bakibon@yahoo.com>
 Ben Bucksch <mozilla@bucksch.org>
 Benedikt Pfeifer <benediktp@ymail.com>
--- a/chat/components/public/imIConversationsService.idl
+++ b/chat/components/public/imIConversationsService.idl
@@ -73,20 +73,22 @@ interface imIConversationsService: nsISu
 // there's an implicit contract that whatever message string the conversation
 // service passes to a protocol, it'll get back as the originalMessage when
 // "new-text" is notified. This is required for the OTR extensions to work.
 
 // A cancellable outgoing message. Before handing a message off to a protocol,
 // the conversation service notifies observers of `preparing-message` and
 // `sending-message` (typically add-ons) of an outgoing message, which can be
 // transformed or cancelled.
-[scriptable, uuid(4391ba5c-9566-41a9-bb9b-fd0a0a490c2c)]
+[scriptable, uuid(f88535b1-0b99-433b-a6de-c1a4bf8b43ea)]
 interface imIOutgoingMessage: nsISupports {
            attribute AUTF8String message;
            attribute boolean cancelled;
+  // Outgoing message is an action command.
+  readonly attribute boolean action;
   readonly attribute prplIConversation conversation;
 };
 
 // A cancellable message to be displayed. When the conversation service is
 // notified of a `new-text` (ie. an incoming or outgoing message to be
 // displayed), it in turn notifies observers of `received-message`
 // (again, typically add-ons), which have the opportunity to swap or cancel
 // the message.
--- a/chat/components/src/imConversations.js
+++ b/chat/components/src/imConversations.js
@@ -16,17 +16,18 @@ XPCOMUtils.defineLazyGetter(this, "bundl
 );
 
 function OutgoingMessage(aMsg, aConversation) {
   this.message = aMsg;
   this.conversation = aConversation;
 }
 OutgoingMessage.prototype = {
   __proto__: ClassInfo("imIOutgoingMessage", "Outgoing Message"),
-  cancelled: false
+  cancelled: false,
+  action: false
 };
 
 function imMessage(aPrplMessage) {
   this.prplMessage = aPrplMessage;
 }
 imMessage.prototype = {
   __proto__: ClassInfo(["imIMessage", "prplIMessage"], "IM Message"),
   cancelled: false,
--- a/chat/protocols/irc/ircCommands.jsm
+++ b/chat/protocols/irc/ircCommands.jsm
@@ -15,16 +15,26 @@ Cu.import("resource:///modules/ircUtils.
 function getConv(aConv) aConv.wrappedJSObject;
 
 // Shortcut to get the JavaScript account object.
 function getAccount(aConv) getConv(aConv)._account;
 
 // Trim leading and trailing spaces and split a string by any type of space.
 function splitInput(aString) aString.trim().split(/\s+/);
 
+function OutgoingMessage(aMsg, aConversation, aAction) {
+  this.message = aMsg;
+  this.conversation = aConversation;
+  this.action = !!aAction;
+}
+OutgoingMessage.prototype = {
+  __proto__: ClassInfo("imIOutgoingMessage", "Outgoing Message"),
+  cancelled: false
+};
+
 // Kick a user from a channel
 // aMsg is <user> [comment]
 function kickCommand(aMsg, aConv) {
   if (!aMsg.length)
     return false;
 
   let params = [aConv.name];
   let offset = aMsg.indexOf(" ");
@@ -60,22 +70,17 @@ function messageCommand(aMsg, aConv, aRe
   let conv = getAccount(aConv).getConversation(nickname);
   if (aReturnedConv)
     aReturnedConv.value = conv;
 
   if (!message.length)
     return true;
 
   // Give add-ons an opportunity to tweak or cancel the message.
-  let om = {
-    __proto__: ClassInfo("imIOutgoingMessage", "Outgoing Message"),
-    message: message,
-    conversation: conv,
-    cancelled: false
-  };
+  let om = new OutgoingMessage(message, conv);
   conv.notifyObservers(om, "sending-message");
   // If a NOTICE is cancelled and resent, it will end up being sent as PRIVMSG.
   if (om.cancelled)
     return true;
 
   return privateMessage(aConv, om.message, nickname, aReturnedConv, aIsNotice);
 }
 
@@ -91,25 +96,32 @@ function setMode(aNickname, aConv, aMode
 }
 
 function actionCommand(aMsg, aConv) {
   // Don't try to send an empty action.
   if (!aMsg || !aMsg.trim().length)
     return false;
 
   let conv = getConv(aConv);
+
+  // Give add-ons an opportunity to tweak or cancel the action.
+  let om = new OutgoingMessage(aMsg, aConv, true);
+  conv.notifyObservers(om, "sending-message");
+  if (om.cancelled)
+    return true;
+
   let account = getAccount(aConv);
-  if (!ctcpCommand(aConv, aConv.name, "ACTION", aMsg)) {
+  if (!ctcpCommand(aConv, aConv.name, "ACTION", om.message)) {
     conv.writeMessage(account._currentServerName, _("error.sendMessageFailed"),
                       {error: true, system: true});
     return true;
   }
 
   // Show the action on our conversation.
-  conv.writeMessage(account._nickname, "/me " + aMsg, {outgoing: true});
+  conv.writeMessage(account._nickname, "/me " + om.message, {outgoing: true});
   return true;
 }
 
 // This will open the conversation, and send and display the text.
 // aReturnedConv is optional and returns the resulting conversation.
 // aIsNotice is optional and sends a NOTICE instead of a PRIVMSG.
 function privateMessage(aConv, aMsg, aNickname, aReturnedConv, aIsNotice) {
   if (!aMsg.length)