Bug 1206238 - Improve XMPP handleErrors to display error system messages directly. r=clokep

This commit is contained in:
aleth 2015-09-23 01:53:34 +02:00
Родитель aab2618a9e
Коммит 56ac95559c
1 изменённых файлов: 60 добавлений и 67 удалений

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

@ -170,39 +170,28 @@ const XMPPMUCConversationPrototype = {
get topic() this._topic,
set topic(aTopic) {
let notAuthorized = (aError) => {
// XEP-0045 (8.1): Unauthorized subject change.
let message = _("conversation.error.changeTopicFailedNotAuthorized");
this.writeMessage(this.name, message, {system: true, error: true});
return true;
};
let errorHandler = this._account.handleErrors({forbidden: notAuthorized,
notAcceptable: notAuthorized,
itemNotFound: notAuthorized});
// XEP-0045 (8.1): Modifying the room subject.
let subject = Stanza.node("subject", null, null, aTopic.trim());
let s = Stanza.message(this.name, null, null,{type: "groupchat"}, subject);
this._account.sendStanza(s, errorHandler);
let notAuthorized = _("conversation.error.changeTopicFailedNotAuthorized");
this._account.sendStanza(s, this._account.handleErrors({
forbidden: notAuthorized,
notAcceptable: notAuthorized,
itemNotFound: notAuthorized
}, this));
},
get topicSettable() true,
/* Called when the user enters a chat message */
sendMsg: function (aMsg) {
let notInRoom = (aError) => {
// If the sender is not in the room.
let from = aError.stanza.attributes["from"];
let message = _("conversation.error.sendFailedAsNotInRoom",
this._account.normalize(from), aMsg);
this.writeMessage(from, message, {system: true, error: true});
return true;
};
let errorHandler = this._account.handleErrors({itemNotFound: notInRoom,
notAcceptable: notInRoom});
// XEP-0045 (7.4): Sending a message to all occupants in a room.
let s = Stanza.message(this.name, aMsg, null, {type: "groupchat"});
this._account.sendStanza(s, errorHandler);
let notInRoom = _("conversation.error.sendFailedAsNotInRoom",
this.name, aMsg);
this._account.sendStanza(s, this._account.handleErrors({
itemNotFound: notInRoom,
notAcceptable: notInRoom
}, this));
},
/* Called by the account when a presence stanza is received for this muc */
@ -472,51 +461,28 @@ const XMPPMUCConversationPrototype = {
// Callback for ban and kick commands.
_banKickHandler: function(aStanza) {
if (aStanza.attributes["type"] == "error") {
let error = this._account.parseError(aStanza);
let message;
switch (error.condition) {
case "not-allowed":
message = _("conversation.error.banKickCommandNotAllowed");
break;
case "conflict":
message = _("conversation.error.banKickCommandConflict");
break;
default:
return false;
}
this.writeMessage(this.name, message, {system: true});
if (aStanza.attributes["type"] == "result")
return true;
}
else if (aStanza.attributes["type"] == "result")
return true;
return false;
let errorHandler = this._account.handleErrors({
notAllowed: _("conversation.error.banKickCommandNotAllowed"),
conflict: _("conversation.error.banKickCommandConflict")
}, this);
return errorHandler(aStanza);
},
// Changes nick in MUC conversation to a new one.
setNick: function(aNewNick) {
let notAcceptable = (aError) => {
// XEP-0045 (7.6): Changing Nickname (example 53).
let message = _("conversation.error.changeNickFailedNotAcceptable",
aNewNick);
this.writeMessage(this.name, message, {system: true, error: true});
// TODO: We should then discover user's reserved nickname (it could be
// discovered before joining a room).
// XEP-0045 (7.12): Discovering Reserved Room Nickname.
return true;
};
let conflict = (aError) => {
// XEP-0045 (7.2.9): Nickname Conflict.
let message = _("conversation.error.changeNickFailedConflict", aNewNick);
this.writeMessage(this.name, message, {system: true, error: true});
return true;
};
let errorHandler = this._account.handleErrors({notAcceptable: notAcceptable,
conflict: conflict});
// XEP-0045 (7.6): Changing Nickname.
let s = Stanza.presence({to: this.name + "/" + aNewNick}, null);
this._account.sendStanza(s, errorHandler);
this._account.sendStanza(s, this._account.handleErrors({
// XEP-0045 (7.6): Changing Nickname (example 53).
// TODO: We should discover if the user has a reserved nickname (maybe
// before joining a room), cf. XEP-0045 (7.12).
notAcceptable: _("conversation.error.changeNickFailedNotAcceptable",
aNewNick),
// XEP-0045 (7.2.9): Nickname Conflict.
conflict: _("conversation.error.changeNickFailedConflict", aNewNick)
}, this));
},
/* Called when the user closed the conversation */
@ -1411,16 +1377,21 @@ const XMPPAccountPrototype = {
},
// Returns an error-handling callback for use with sendStanza generated
// from aHandlers, an object containing the error handlers.
// If the stanza passed to the callback is an error stanza, and
// aHandlers contains a method with the name of the defined condition
// of the error, that method is called. It should return true if the
// error was handled.
// from aHandlers, an object defining the error handlers.
// If the stanza passed to the callback is an error stanza, it checks if
// aHandlers contains a property with the name of the defined condition
// of the error.
// * If the property is a function, it is called with the parsed error
// as its argument, bound to aThis (if provided).
// It should return true if the error was handled.
// * If the property is a string, it is displayed as a system message
// in the conversation given by aThis.
handleErrors(aHandlers, aThis) {
return (aStanza) => {
let error = this.parseError(aStanza);
if (!error)
return false;
let toCamelCase = aStr => {
// Turn defined condition string into a valid camelcase
// JS property name.
@ -1429,9 +1400,31 @@ const XMPPAccountPrototype = {
return uncapitalize(aStr.split("-").map(capitalize).join(""));
}
let condition = toCamelCase(error.condition);
// Check if we have a handler property for this kind of error.
if (!(condition in aHandlers))
return false;
return aHandlers[condition].call(aThis, error);
let handler = aHandlers[condition];
if (typeof handler == "string") {
// The string is an error message to be displayed in the conversation.
if (!aThis || !aThis.writeMessage) {
this.ERROR("HandleErrors was passed an error message string, but " +
"no conversation to display it in:\n" + handler);
return true;
}
aThis.writeMessage(aThis.name, handler, {system: true, error: true});
return true;
}
else if (typeof handler == "function") {
// If we're given a function, call this error handler.
return handler.call(aThis, error);
}
else {
// If this happens, there's a bug somewhere.
this.ERROR("HandleErrors was passed a handler for '" + condition +
"'' which is neither a function nor a string.");
return false;
}
};
},