Bug 1929105 - Automatically reload the displayed email message if reading an offline copy failed. r=aleca,BenC,KaiE

Depends on D228621.

Differential Revision: https://phabricator.services.mozilla.com/D228930
This commit is contained in:
Geoff Lankow 2024-11-14 09:01:17 +00:00
Родитель ec81af2a4d
Коммит 0f5ca9f218
4 изменённых файлов: 120 добавлений и 6 удалений

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

@ -14,7 +14,7 @@
// msgHdrView.js
/* globals AdjustHeaderView ClearCurrentHeaders ClearPendingReadTimer
HideMessageHeaderPane OnLoadMsgHeaderPane OnTagsChange
HideMessageHeaderPane initFolderDBListener OnLoadMsgHeaderPane OnTagsChange
OnUnloadMsgHeaderPane HandleAllAttachments AttachmentMenuController */
var { MailServices } = ChromeUtils.importESModule(
@ -203,6 +203,7 @@ function displayMessage(uri, viewWrapper) {
const messageService = MailServices.messageServiceFromURI(uri);
gMessage = messageService.messageURIToMsgHdr(uri);
gFolder = gMessage.folder;
initFolderDBListener();
messageHistory.push(uri);

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

@ -222,6 +222,16 @@ class FolderDBListener {
) {
updateStarButton();
}
// If the offline flag gets removed, reload to download the message again.
// This could happen if the message's storeToken points to a bogus place in
// the message store.
if (
oldFlags & Ci.nsMsgMessageFlags.Offline &&
!(newFlags & Ci.nsMsgMessageFlags.Offline)
) {
ReloadMessage();
}
}
onHdrDeleted() {}
onHdrAdded() {}
@ -1357,11 +1367,6 @@ function ClearCurrentHeaders() {
function ShowMessageHeaderPane() {
document.getElementById("msgHeaderView").collapsed = false;
document.getElementById("mail-notification-top").collapsed = false;
// Initialize the DBListener if we don't have one. This might happen when the
// message pane is hidden or no message was selected before, which caused the
// clearing of the the DBListener.
initFolderDBListener();
}
function HideMessageHeaderPane() {

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

@ -79,6 +79,7 @@ skip-if = os == 'mac'
[browser_navigation.js]
[browser_paneFocus.js]
[browser_preferDisplayName.js]
[browser_reloadBadMessage.js]
[browser_repairFolder.js]
[browser_quota.js]
[browser_searchMessages.js]

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

@ -0,0 +1,107 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Tests that a message with a bad storeToken is automatically reloaded and
* stored again.
*/
const { IMAPServer } = ChromeUtils.importESModule(
"resource://testing-common/IMAPServer.sys.mjs"
);
const { MessageGenerator } = ChromeUtils.importESModule(
"resource://testing-common/mailnews/MessageGenerator.sys.mjs"
);
let imapFolder;
add_setup(async function () {
const generator = new MessageGenerator();
const account = MailServices.accounts.createLocalMailAccount();
const imapServer = new IMAPServer();
const imapAccount = MailServices.accounts.createAccount();
imapAccount.addIdentity(MailServices.accounts.createIdentity());
imapAccount.incomingServer = MailServices.accounts.createIncomingServer(
`${imapAccount.key}user`,
"localhost",
"imap"
);
imapAccount.incomingServer.port = imapServer.port;
imapAccount.incomingServer.username = "user";
imapAccount.incomingServer.password = "password";
const imapRootFolder = imapAccount.incomingServer.rootFolder;
imapFolder = imapRootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Inbox);
await imapServer.addMessages(imapFolder, generator.makeMessages({}));
registerCleanupFunction(async () => {
await promiseServerIdle(imapAccount.incomingServer);
MailServices.accounts.removeAccount(account, false);
MailServices.accounts.removeAccount(imapAccount, false);
});
});
add_task(async function () {
const tabmail = document.getElementById("tabmail");
const about3Pane = tabmail.currentAbout3Pane;
const messagePaneBrowser =
about3Pane.messageBrowser.contentWindow.getMessagePaneBrowser();
about3Pane.restoreState({
folderURI: imapFolder.URI,
messagePaneVisible: true,
});
await BrowserTestUtils.waitForCondition(() => {
for (const m of imapFolder.messages) {
if (!(m.flags & Ci.nsMsgMessageFlags.Offline)) {
return false;
}
}
return true;
}, "waiting for message list to finish downloading");
let mboxSize = imapFolder.filePath.fileSize;
const messages = [...imapFolder.messages];
Assert.equal(messages[0].storeToken, "0", "first storeToken should be 0");
messages[0].storeToken = "1234"; // Much less than mboxSize.
messages[1].storeToken = "12345678"; // Much greater than mboxSize.
messages[2].storeToken = String(mboxSize - 2); // Near mboxSize, just in case.
messages[3].storeToken = String(mboxSize + 2);
for (let i = 0; i <= 3; i++) {
// Load the message. Attempting to load a message with a bad storeToken
// should cause it to be downloaded again from the server (you can verify
// this with MOZ_LOG=IMAP:4) and written to the mbox.
const loadedPromise = BrowserTestUtils.browserLoaded(
messagePaneBrowser,
false,
url => url.endsWith(messages[i].messageKey)
);
about3Pane.threadTree.selectedIndex = i;
await loadedPromise;
Assert.stringContains(
messagePaneBrowser.contentDocument.body.textContent,
"Hello " + messages[i].recipients.replace(/^"(.*)".*$/, "$1"),
"actual message content should load"
);
Assert.equal(
messages[i].storeToken,
String(mboxSize),
"message should have been rewritten at the end of the mbox file"
);
Assert.greater(
imapFolder.filePath.fileSize,
mboxSize,
"message should have been rewritten at the end of the mbox file"
);
Assert.ok(
messages[i].flags & Ci.nsMsgMessageFlags.Offline,
"message has regained the offline flag"
);
mboxSize = imapFolder.filePath.fileSize;
}
});