Bug 1762690 - Start idle only if ImapClient is still online. r=mkmelin

Differential Revision: https://phabricator.services.mozilla.com/D164530

--HG--
extra : amend_source : 8c143a19df108500126c85452226ecda158a5081
This commit is contained in:
Ping Chen 2022-12-13 21:29:00 +11:00
Родитель 20d56874cf
Коммит cc54b03f9a
3 изменённых файлов: 42 добавлений и 30 удалений

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

@ -73,6 +73,13 @@ class ImapClient {
this._loadPrefs();
}
/**
* @type {boolean} - Whether the socket is open.
*/
get isOnline() {
return this._socket?.readyState == "open";
}
/**
* Load imap related preferences, many behaviors depend on these pref values.
*/
@ -105,7 +112,7 @@ class ImapClient {
* Initiate a connection to the server
*/
connect() {
if (this._socket?.readyState == "open") {
if (this.isOnline) {
// Reuse the connection.
this.onReady();
this._setSocketTimeout(this._prefs.tcpTimeout);
@ -129,7 +136,7 @@ class ImapClient {
* @param {number} timeout - The timeout in seconds.
*/
_setSocketTimeout(timeout) {
this._socket.transport.setTimeout(
this._socket.transport?.setTimeout(
Ci.nsISocketTransport.TIMEOUT_READ_WRITE,
timeout
);
@ -638,14 +645,16 @@ class ImapClient {
}
};
this._sendTagged("IDLE");
this._setSocketTimeout(PR_UINT32_MAX);
this._idling = true;
this._idleTimer = setTimeout(() => {
this.endIdle(() => {
this._actionNoop();
});
// Per rfc2177, should terminate the IDLE and re-issue it at least every
// 29 minutes.
}, 20 * 60 * 1000);
// 29 minutes. But in practice many servers timeout before that. A noop
// every 5min is better than timeout.
}, 5 * 60 * 1000);
this._logger.debug(`Idling in ${this.folder.URI}`);
}
@ -767,7 +776,7 @@ class ImapClient {
this._logger.debug(`C: ${str}`);
}
if (this._socket?.readyState != "open") {
if (!this.isOnline) {
if (!str.includes("LOGOUT")) {
this._logger.warn(
`Failed to send because socket state is ${this._socket?.readyState}`
@ -1615,7 +1624,6 @@ class ImapClient {
this._reset();
// Tell ImapIncomingServer this client can be reused now.
this.onFree?.();
this._setSocketTimeout(PR_UINT32_MAX);
};
/** @see nsIImapProtocol */

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

@ -550,33 +550,38 @@ class ImapIncomingServer extends MsgIncomingServer {
if (!client) {
return;
}
client.onFree = async () => {
let startIdle = async () => {
if (!this.useIdle || !this._capabilities.includes("IDLE")) {
return;
}
// IDLE is configed and supported, use IDLE to receive server pushes.
let hasInboxConnection = this._connections.some(c =>
this._isInboxConnection(c)
);
let alreadyIdling =
client.folder &&
this._connections.find(
c => c != client && !c.busy && c.folder == client.folder
);
if (!hasInboxConnection) {
client.selectFolder(
this.rootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Inbox)
);
} else if (client.folder && !alreadyIdling) {
client.idle();
} else if (alreadyIdling) {
client.folder = null;
}
};
client.onFree = () => {
client.busy = false;
let resolve = this._connectionWaitingQueue.shift();
if (resolve) {
// Resolve the first waiting in queue.
resolve(true);
} else {
let hasInboxConnection = this._connections.some(c =>
this._isInboxConnection(c)
);
let alreadyIdling =
client.folder &&
this._connections.find(
c => c != client && !c.busy && c.folder == client.folder
);
if (this.useIdle && this._capabilities.includes("IDLE")) {
// IDLE is configed and supported, use IDLE to receive server pushes.
if (!hasInboxConnection) {
client.selectFolder(
this.rootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Inbox)
);
} else if (client.folder && !alreadyIdling) {
client.idle();
} else if (alreadyIdling) {
client.folder = null;
}
}
} else if (client.isOnline) {
startIdle();
}
};
handler(client);

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

@ -428,8 +428,7 @@ class ImapService {
* instance, and do some actions.
*/
_withClient(folder, handler) {
let server = folder.QueryInterface(Ci.nsIMsgImapMailFolder)
.imapIncomingServer;
let server = folder.server.QueryInterface(Ci.nsIMsgIncomingServer);
let runningUrl = Services.io
.newURI(`imap://${server.hostName}:${server.port}`)
.QueryInterface(Ci.nsIMsgMailNewsUrl);