Bug 1014472 - Support automatic MUC reconnection for all protocols. r=clokep, florian

This commit is contained in:
aleth 2014-07-04 21:36:04 +02:00
Родитель d1f16207c4
Коммит 0f0c5d9fa6
8 изменённых файлов: 57 добавлений и 39 удалений

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

@ -11,6 +11,7 @@ interface imIAccountBuddy;
interface imIAccount;
interface nsIURI;
interface nsIDOMDocument;
interface prplIChatRoomFieldValues;
/*
* This is the XPCOM purple conversation component, a proxy for PurpleConversation.
@ -86,7 +87,7 @@ interface prplIConvIM: prplIConversation {
readonly attribute short typingState;
};
[scriptable, uuid(91ad2ce5-f886-4653-ac75-ac22bed4ec7a)]
[scriptable, uuid(47b42861-364a-477d-88a1-4616a7060df2)]
interface prplIConvChat: prplIConversation {
/* Get an nsISimpleEnumerator of prplIConvChatBuddy objects:
@ -119,6 +120,12 @@ interface prplIConvChat: prplIConversation {
/* This is true if we are in the process of joining the channel */
readonly attribute boolean joining;
/* This stores the data required to join the chat with joinChat().
If null, the chat will not be rejoined automatically when the
account reconnects after a disconnect.
Should be set to null by the prpl if the user parts the chat. */
readonly attribute prplIChatRoomFieldValues chatRoomFields;
/* Observers will receive chat-buddy-add, chat-buddy-update,
chat-buddy-remove and chat-update-topic notifications.

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

@ -248,14 +248,24 @@ UIConversation.prototype = {
connected: function() {
if (this._disconnected) {
delete this._disconnected;
if (!this.isChat)
let msg = bundle.GetStringFromName("accountReconnected");
if (this.isChat) {
if (!this._wasLeft) {
this.systemMessage(msg);
// Reconnect chat if possible.
let chatRoomFields = this.target.chatRoomFields;
if (chatRoomFields)
this.account.joinChat(chatRoomFields);
}
delete this._wasLeft;
}
else {
this._justReconnected = true;
// Exclude convs with contacts, these receive presence info updates
// (and therefore a reconnected message).
if ((this.isChat && !this._wasLeft) ||
(!this.isChat && !this.contact))
this.systemMessage(bundle.GetStringFromName("accountReconnected"));
delete this._wasLeft;
if (!this.contact)
this.systemMessage(msg);
}
}
this.notifyObservers(this, "update-buddy-status");
},

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

@ -531,6 +531,11 @@ const GenericConvChatPrototype = {
get isChat() true,
// Stores the prplIChatRoomFieldValues required to join this channel
// to enable later reconnections. If null, the MUC will not be reconnected
// automatically after disconnections.
chatRoomFields: null,
_topic: "",
_topicSetter: null,
get topic() this._topic,

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

@ -288,11 +288,6 @@ ircChannel.prototype = {
aProperties);
},
// Stores the prplIChatRoomFieldValues required to join this channel
// to enable later reconnections. If absent, the MUC will not be reconnected
// automatically after disconnections.
_chatRoomFields: null,
// Section 3.2.2 of RFC 2812.
part: function(aMessage) {
let params = [this.name];
@ -306,7 +301,7 @@ ircChannel.prototype = {
this._account.sendMessage("PART", params);
// Remove reconnection information.
delete this._chatRoomFields;
delete this.chatRoomFields;
},
close: function() {
@ -446,8 +441,8 @@ ircChannel.prototype = {
let key = getNextParam();
// A new channel key was set, display a message if this key is not
// already known.
if (this._chatRoomFields &&
this._chatRoomFields.getValue("password") == key) {
if (this.chatRoomFields &&
this.chatRoomFields.getValue("password") == key) {
continue;
}
msg = _("message.channelKeyAdded", aSetter, key);
@ -458,7 +453,7 @@ ircChannel.prototype = {
this.writeMessage(aSetter, msg, {system: true});
// Store the new fields for reconnect.
this._chatRoomFields =
this.chatRoomFields =
this._account.getChatRoomDefaultFieldValues(newFields);
}
else if (aNewMode[i] == "b") {
@ -1450,15 +1445,19 @@ ircAccount.prototype = {
let key = aComponents.getValue("password");
if (key)
params.push(key);
let defaultName = key ? channel + " " + key : channel;
// Send the join command, but don't log the channel key.
this.sendMessage("JOIN", params,
"JOIN " + channel + (key ? " <key not logged>" : ""));
// Open conversation early for better responsiveness.
let conv = this.getConversation(channel);
// Store the prplIChatRoomFieldValues to enable later reconnections.
conv._chatRoomFields = this.getChatRoomDefaultFieldValues(defaultName);
conv.joining = true;
// Store the prplIChatRoomFieldValues to enable later reconnections.
let defaultName = key ? channel + " " + key : channel;
conv.chatRoomFields = this.getChatRoomDefaultFieldValues(defaultName);
return conv;
},

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

@ -177,19 +177,19 @@ var ircBase = {
conversation.joining = false;
// If the user parted from this room earlier, confirm the rejoin.
// If conversation._chatRoomFields is present, the rejoin was due to
// If conversation.chatRoomFields is present, the rejoin was due to
// an automatic reconnection, for which we already notify the user.
if (!conversation._firstJoin && !conversation._chatRoomFields) {
if (!conversation._firstJoin && !conversation.chatRoomFields) {
conversation.writeMessage(aMessage.nickname, _("message.rejoined"),
{system: true});
}
delete conversation._firstJoin;
// Ensure chatRoomFields information is available for reconnection.
if (!conversation._chatRoomFields) {
if (!conversation.chatRoomFields) {
this.WARN("Opening a MUC without storing its " +
"prplIChatRoomFieldValues first.");
conversation._chatRoomFields =
conversation.chatRoomFields =
this.getChatRoomDefaultFieldValues(channelName);
}
}
@ -323,7 +323,6 @@ var ircBase = {
},
"001": function(aMessage) { // RPL_WELCOME
// Welcome to the Internet Relay Network <nick>!<user>@<host>
this.reportConnected();
this._socket.resetPingTimer();
this._currentServerName = aMessage.servername;
@ -345,12 +344,8 @@ var ircBase = {
// Check if any of our buddies are online!
this.sendIsOn();
// Reconnect channels if they were not parted by the user.
this.conversations.forEach(conversation => {
if (conversation.isChat && conversation._chatRoomFields)
this.joinChat(conversation._chatRoomFields);
});
// Done!
this.reportConnected();
return serverMessage(this, aMessage);
},
"002": function(aMessage) { // RPL_YOURHOST

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

@ -205,10 +205,10 @@ var commands = [
if (!conv.isChat || !conv.left)
return false;
// Rejoin the current channel. If the channel was explicitly parted
// by the user, _chatRoomFields will have been deleted.
// by the user, chatRoomFields will have been deleted.
// Otherwise, make use of it (e.g. if the user was kicked).
if (conv._chatRoomFields) {
account.joinChat(conv._chatRoomFields);
if (conv.chatRoomFields) {
account.joinChat(conv.chatRoomFields);
return true;
}
params = [conv.name];

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

@ -231,9 +231,9 @@ function conversationErrorMessage(aAccount, aMessage, aError,
if (aJoinFailed)
conv.joining = false;
// If the conversation cannot be rejoined automatically, delete
// _chatRoomFields.
// chatRoomFields.
if (!aRejoinable)
delete conv._chatRoomFields;
delete conv.chatRoomFields;
}
return true;

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

@ -653,7 +653,7 @@ const XMPPAccountPrototype = {
this._mucs[jid].left = false; // We are rejoining.
}
else
this._mucs[jid] = nick;
this._mucs[jid] = aComponents;
let x;
let password = aComponents.getValue("password");
@ -848,15 +848,17 @@ const XMPPAccountPrototype = {
else if (jid in this._buddies)
this._buddies[jid].onPresenceStanza(aStanza);
else if (jid in this._mucs) {
if (typeof(this._mucs[jid]) == "string") {
if (this._mucs[jid] instanceof Ci.prplIChatRoomFieldValues) {
// We have attempted to join, but not created the conversation yet.
if (aStanza.attributes["type"] == "error") {
delete this._mucs[jid];
this.ERROR("Failed to join MUC: " + aStanza.convertToString());
return;
}
let nick = this._mucs[jid];
let chatRoomFields = this._mucs[jid];
let nick = chatRoomFields.getValue("nick");
this._mucs[jid] = new this._MUCConversationConstructor(this, jid, nick);
this._mucs[jid].chatRoomFields = chatRoomFields;
}
this._mucs[jid].onPresenceStanza(aStanza);
}