diff --git a/mail/components/extensions/parent/ext-mail.js b/mail/components/extensions/parent/ext-mail.js index 03affb6da4..50f6389b08 100644 --- a/mail/components/extensions/parent/ext-mail.js +++ b/mail/components/extensions/parent/ext-mail.js @@ -18,6 +18,8 @@ var { ExtensionSupport } = ChromeUtils.importESModule( ChromeUtils.defineESModuleGetters(this, { ExtensionContent: "resource://gre/modules/ExtensionContent.sys.mjs", + setTimeout: "resource://gre/modules/Timer.sys.mjs", + clearTimeout: "resource://gre/modules/Timer.sys.mjs", }); XPCOMUtils.defineLazyModuleGetters(this, { @@ -2738,12 +2740,29 @@ class MessageList { this.extension = extension; this.isDone = false; this.pages = []; + this.autoPaginatorTimeout = null; + this.addPage(); } addPage() { + if (this.autoPaginatorTimeout) { + clearTimeout(this.autoPaginatorTimeout); + this.autoPaginatorTimeout = null; + } + + if (this.isDone) { + return; + } + // Adding a page will make this.currentPage point to the new page. let previousPage = this.currentPage; + + // If the current page has no messages, there is no need to add a page. + if (previousPage && previousPage.messages.length == 0) { + return; + } + this.pages.push(new MessagePage()); // The previous page is finished and can be resolved. if (previousPage) { @@ -2766,7 +2785,15 @@ class MessageList { if (this.currentPage.messages.length >= gMessagesPerPage) { this.addPage(); } + this.currentPage.messages.push(convertMessage(message, this.extension)); + + // Automatically push a new page and return the page with this message after + // a fixed amount of time, so that small sets of search results are not held + // back until a full page has been found or the entire search has finished. + if (!this.autoPaginatorTimeout) { + this.autoPaginatorTimeout = setTimeout(this.addPage.bind(this), 1000); + } } done() { @@ -2823,6 +2850,9 @@ var messageListTracker = { * Add messages to a messageList. */ async _addMessages(messages, messageList) { + if (messageList.isDone) { + return; + } if (Array.isArray(messages)) { messages = this._createEnumerator(messages); } @@ -2960,3 +2990,7 @@ extensions.on("startup", (type, extension) => { () => new WindowManager(extension) ); }); + +extensions.on("shutdown", (type, extension) => { + messageListTracker._contextLists.delete(extension); +}); diff --git a/mail/components/extensions/parent/ext-messages.js b/mail/components/extensions/parent/ext-messages.js index 39dbea041b..45d654d049 100644 --- a/mail/components/extensions/parent/ext-messages.js +++ b/mail/components/extensions/parent/ext-messages.js @@ -744,6 +744,13 @@ this.messages = class extends ExtensionAPIPersistent { ); return messageListTracker.getNextPage(messageList); }, + async abortList(messageListId) { + let messageList = messageListTracker.getList( + messageListId, + context.extension + ); + messageList.done(); + }, async get(messageId) { let msgHdr = messageTracker.getMessage(messageId); if (!msgHdr) { @@ -1181,6 +1188,9 @@ this.messages = class extends ExtensionAPIPersistent { if (messages) { for (let msg of [...messages]) { + if (messageList.isDone) { + return; + } if (await checkSearchCriteria(folder, msg)) { messageList.addMessage(msg); } @@ -1189,6 +1199,9 @@ this.messages = class extends ExtensionAPIPersistent { if (includeSubFolders) { for (let subFolder of folder.subFolders) { + if (messageList.isDone) { + return; + } await searchMessages(subFolder, messageList, true); } } @@ -1200,9 +1213,12 @@ this.messages = class extends ExtensionAPIPersistent { includeSubFolders = false ) => { for (let folder of folders) { + if (messageList.isDone) { + return; + } await searchMessages(folder, messageList, includeSubFolders); } - return messageList.done(); + messageList.done(); }; // Prepare case insensitive me filtering. diff --git a/mail/components/extensions/schemas/messages.json b/mail/components/extensions/schemas/messages.json index 6a025763a1..a3d72d0e83 100644 --- a/mail/components/extensions/schemas/messages.json +++ b/mail/components/extensions/schemas/messages.json @@ -414,6 +414,18 @@ } ] }, + { + "name": "abortList", + "type": "function", + "description": "Finalizes the specified list and terminates any process currently still adding messages.", + "async": true, + "parameters": [ + { + "name": "messageListId", + "type": "string" + } + ] + }, { "name": "get", "type": "function",