diff options
Diffstat (limited to 'comm/mail/test/browser/openpgp/composition')
8 files changed, 2832 insertions, 0 deletions
diff --git a/comm/mail/test/browser/openpgp/composition/browser.ini b/comm/mail/test/browser/openpgp/composition/browser.ini new file mode 100644 index 0000000000..794baf5250 --- /dev/null +++ b/comm/mail/test/browser/openpgp/composition/browser.ini @@ -0,0 +1,23 @@ +[DEFAULT] +head=head.js +prefs = + browser.tabs.remote.autostart=false + mail.provider.suppress_dialog_on_startup=true + mail.spotlight.firstRunDone=true + mail.winsearch.firstRunDone=true + mailnews.start_page.override_url=about:blank + mailnews.start_page.url=about:blank +subsuite = thunderbird +support-files = ../data/** + +[browser_composeSigned.js] +skip-if = debug # Bug 1673652 - L10NRegistry throws NS_ERROR_FILE_UNRECOGNIZED_PATH +[browser_composeSigned2.js] +skip-if = debug # Bug 1673652 - L10NRegistry throws NS_ERROR_FILE_UNRECOGNIZED_PATH +[browser_composeEncrypted.js] +skip-if = debug # Bug 1673652 - L10NRegistry throws NS_ERROR_FILE_UNRECOGNIZED_PATH +[browser_composeSwitchIdentity.js] +skip-if = debug # Bug 1673652 - L10NRegistry throws NS_ERROR_FILE_UNRECOGNIZED_PATH +[browser_editDraftTemplate.js] +[browser_expiredKey.js] +skip-if = debug # Bug 1673652 - L10NRegistry throws NS_ERROR_FILE_UNRECOGNIZED_PATH diff --git a/comm/mail/test/browser/openpgp/composition/browser_composeEncrypted.js b/comm/mail/test/browser/openpgp/composition/browser_composeEncrypted.js new file mode 100644 index 0000000000..bd58241bd0 --- /dev/null +++ b/comm/mail/test/browser/openpgp/composition/browser_composeEncrypted.js @@ -0,0 +1,976 @@ +/* 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 for OpenPGP encrypted message composition. + */ + +"use strict"; + +const { + open_message_from_file, + be_in_folder, + get_about_message, + get_special_folder, + press_delete, + select_click_row, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +const { + close_compose_window, + open_compose_new_mail, + open_compose_with_reply, + save_compose_message, + setup_msg_contents, +} = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm"); +const { close_window } = ChromeUtils.import( + "resource://testing-common/mozmill/WindowHelpers.jsm" +); +const { OpenPGPTestUtils } = ChromeUtils.import( + "resource://testing-common/mozmill/OpenPGPTestUtils.jsm" +); + +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +let bobAcct; +let bobIdentity; +let gOutbox; +let gDrafts; + +let aboutMessage = get_about_message(); + +// Used in some of the tests to verify key status display. +let l10n = new Localization(["messenger/openpgp/composeKeyStatus.ftl"]); + +function waitForComposeWindow() { + return BrowserTestUtils.domWindowOpened(null, async win => { + await BrowserTestUtils.waitForEvent(win, "load"); + await BrowserTestUtils.waitForEvent(win, "focus", true); + return ( + win.document.documentURI === + "chrome://messenger/content/messengercompose/messengercompose.xhtml" + ); + }); +} + +/** + * Closes a window with a <dialog> element by calling the acceptDialog(). + * + * @param {Window} win + */ +async function closeDialog(win) { + let closed = BrowserTestUtils.domWindowClosed(win); + win.document.documentElement.querySelector("dialog").acceptDialog(); + await closed; +} + +function setAutoPrefs(autoEnable, autoDisable, notifyOnDisable) { + Services.prefs.setBoolPref("mail.e2ee.auto_enable", autoEnable); + Services.prefs.setBoolPref("mail.e2ee.auto_disable", autoDisable); + Services.prefs.setBoolPref( + "mail.e2ee.notify_on_auto_disable", + notifyOnDisable + ); +} + +function clearAutoPrefs() { + Services.prefs.clearUserPref("mail.e2ee.auto_enable"); + Services.prefs.clearUserPref("mail.e2ee.auto_disable"); + Services.prefs.clearUserPref("mail.e2ee.notify_on_auto_disable"); +} + +async function waitCheckEncryptionStateDone(win) { + return BrowserTestUtils.waitForEvent( + win.document, + "encryption-state-checked" + ); +} + +/** + * Setup a mail account with a private key and import the public key for the + * receiver. + */ +add_setup(async function () { + // Encryption makes the compose process a little longer. + requestLongerTimeout(5); + + bobAcct = MailServices.accounts.createAccount(); + bobAcct.incomingServer = MailServices.accounts.createIncomingServer( + "bob", + "openpgp.example", + "imap" + ); + bobIdentity = MailServices.accounts.createIdentity(); + bobIdentity.email = "bob@openpgp.example"; + bobAcct.addIdentity(bobIdentity); + + let [id] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/bob@openpgp.example-0xfbfcc82a015e7330-secret.asc" + ) + ) + ); + + Assert.ok(id, "private key id received"); + bobIdentity.setUnicharAttribute("openpgp_key_id", id.split("0x").join("")); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/alice@openpgp.example-0xf231550c4f47e38e-pub.asc" + ) + ) + ); + + gOutbox = await get_special_folder(Ci.nsMsgFolderFlags.Queue); + gDrafts = await get_special_folder(Ci.nsMsgFolderFlags.Drafts, true); +}); + +/** + * Tests composition of an encrypted only message shows as encrypted in + * the Outbox. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedMessageComposition( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Encrypted Message", + "This is an encrypted message with key composition test." + ); + await checkDonePromise; + + if (!autoEnable) { + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + } + + Assert.ok(composeWin.gSendEncrypted, "message encryption should be on"); + Assert.ok(composeWin.gSendSigned, "message signing should be on"); + await OpenPGPTestUtils.toggleMessageSigning(composeWin); + + Assert.ok( + !composeWin.gSendSigned, + "toggling message signing should have completed already" + ); + + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + select_click_row(0); + + await TestUtils.waitForCondition( + () => OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "message should have encrypted icon" + ); + + Assert.equal( + aboutMessage.document.querySelector("#attachmentList").itemChildren.length, + 0, + "no keys should be attached to message" + ); + + Assert.ok( + OpenPGPTestUtils.hasNoSignedIconState(aboutMessage.document), + "message should have no signed icon" + ); + + // Delete the message so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); +} + +add_task(async function testEncryptedMessageCompositionAutoEncOff() { + await testEncryptedMessageComposition(false, false, false); +}); + +add_task(async function testEncryptedMessageCompositionAutoEncOnAutoDisOff() { + await testEncryptedMessageComposition(true, false, false); +}); + +add_task(async function testEncryptedMessageCompositionAutoEncOnAutoDisOn() { + await testEncryptedMessageComposition(true, true, false); +}); + +/** + * Tests composition of an encrypted only message, with public key attachment + * enabled, shows as encrypted in the Outbox. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedMessageWithKeyComposition( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Encrypted Message With Key", + "This is an encrypted message with key composition test." + ); + await checkDonePromise; + + if (!autoEnable) { + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + } + + await OpenPGPTestUtils.toggleMessageSigning(composeWin); + await OpenPGPTestUtils.toggleMessageKeyAttachment(composeWin); + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + select_click_row(0); + + await TestUtils.waitForCondition( + () => OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "message should have encrypted icon" + ); + + let attachmentList = aboutMessage.document.querySelector("#attachmentList"); + + await TestUtils.waitForCondition( + () => attachmentList.itemChildren.length == 1, + "message should have one attachment" + ); + + Assert.ok( + attachmentList + .getItemAtIndex(0) + .attachment.name.includes(OpenPGPTestUtils.BOB_KEY_ID), + "attachment name should contain Bob's key id" + ); + + Assert.ok( + OpenPGPTestUtils.hasNoSignedIconState(aboutMessage.document), + "message should have no signed icon" + ); + + // Delete the message so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); +} + +add_task(async function testEncryptedMessageWithKeyCompositionAutoEncOff() { + await testEncryptedMessageWithKeyComposition(false, false, false); +}); + +add_task( + async function testEncryptedMessageWithKeyCompositionAutoEncOnAutoDisOff() { + await testEncryptedMessageWithKeyComposition(true, false, false); + } +); + +add_task( + async function testEncryptedMessageWithKeyCompositionAutoEncOnAutoDisOn() { + await testEncryptedMessageWithKeyComposition(true, true, false); + } +); + +/** + * Tests composition of an encrypted message to a recipient, whom we have no + * key for, prompts the user. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedRecipientKeyNotAvailabeMessageComposition( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "carol@example.com", + "Compose Encrypted Recipient Key Not Available Message", + "This is an encrypted recipient key not available message composition test." + ); + await checkDonePromise; + + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + + let kaShown = BrowserTestUtils.waitForCondition( + () => composeWin.document.getElementById("keyAssistant").open, + "Timeout waiting for the #keyAssistant to be visible" + ); + + composeWin.goDoCommand("cmd_sendLater"); + await kaShown; + + await BrowserTestUtils.closeWindow(composeWin); +} + +add_task( + async function testEncryptedRecipientKeyNotAvailabeMessageCompositionAutoEncOff() { + await testEncryptedRecipientKeyNotAvailabeMessageComposition( + false, + false, + false + ); + } +); + +add_task( + async function testEncryptedRecipientKeyNotAvailabeMessageCompositionAutoEncOnAutoDisOff() { + await testEncryptedRecipientKeyNotAvailabeMessageComposition( + true, + false, + false + ); + } +); + +add_task( + async function testEncryptedRecipientKeyNotAvailabeMessageCompositionAutoEncOnAutoDisOn() { + await testEncryptedRecipientKeyNotAvailabeMessageComposition( + true, + true, + false + ); + } +); + +/** + * Tests that we turn on encryption automatically for the first recipient + * (key available), and that we turn off encryption automatically after + * adding the second recipient (key not available). + */ +add_task(async function testEncryptedRecipientKeyNotAvailabeAutoDisable() { + setAutoPrefs(true, true, false); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Encrypted Recipient Key Not Available Message", + "This is an encrypted recipient key not available message composition test." + ); + await checkDonePromise; + + Assert.ok(composeWin.gSendEncrypted, "message encryption should be on"); + + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents(cwc, " missing@openpgp.example ", "", ""); + await checkDonePromise; + + Assert.ok(!composeWin.gSendEncrypted, "message encryption should be off"); + + await sendMessage(composeWin); + await be_in_folder(gOutbox); + select_click_row(0); + + await TestUtils.waitForCondition( + () => OpenPGPTestUtils.hasNoEncryptedIconState(aboutMessage.document), + "message should not have encrypted icon" + ); + + // Clean up so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); +}); + +/** + * Tests composition of an encrypted message to a recipient, whose key we have + * not accepted, prompts the user. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedRecipientKeyNotAcceptedMessageComposition( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/carol@example.com-0x3099ff1238852b9f-pub.asc" + ) + ), + OpenPGPTestUtils.ACCEPTANCE_UNDECIDED + ); + + for (let level of [ + OpenPGPTestUtils.ACCEPTANCE_UNDECIDED, + OpenPGPTestUtils.ACCEPTANCE_REJECTED, + ]) { + info(`Testing with acceptance level: "${level}"...`); + await OpenPGPTestUtils.updateKeyIdAcceptance( + OpenPGPTestUtils.CAROL_KEY_ID, + level + ); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "carol@example.com", + "Compose Encrypted Recipient Key Not Accepted", + "This is an encrypted recipient key not accepted message composition test." + ); + await checkDonePromise; + + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + + let kaShown = BrowserTestUtils.waitForCondition( + () => composeWin.document.getElementById("keyAssistant").open, + "Timeout waiting for the #keyAssistant to be visible" + ); + + composeWin.goDoCommand("cmd_sendLater"); + await kaShown; + + await BrowserTestUtils.closeWindow(composeWin); + } + await OpenPGPTestUtils.removeKeyById(OpenPGPTestUtils.CAROL_KEY_ID); +} + +add_task( + async function testEncryptedRecipientKeyNotAcceptedMessageCompositionAutoEncOff() { + await testEncryptedRecipientKeyNotAcceptedMessageComposition( + false, + false, + false + ); + } +); + +add_task( + async function testEncryptedRecipientKeyNotAcceptedMessageCompositionAutoEncOnAutoDisOff() { + await testEncryptedRecipientKeyNotAcceptedMessageComposition( + true, + false, + false + ); + } +); + +add_task( + async function testEncryptedRecipientKeyNotAcceptedMessageCompositionAutoEncOnAutoDisOn() { + await testEncryptedRecipientKeyNotAcceptedMessageComposition( + true, + true, + false + ); + } +); + +/** + * Tests composition of an encrypted message to a recipient, whose key we have + * accepted (not verified), shows as encrypted in the Outbox. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedRecipientKeyUnverifiedMessageComposition( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/carol@example.com-0x3099ff1238852b9f-pub.asc" + ) + ), + OpenPGPTestUtils.ACCEPTANCE_UNVERIFIED + ); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "carol@example.com", + "Compose Encrypted Recipient Key Unverified Message", + "This is an encrypted, recipient key unverified message test." + ); + await checkDonePromise; + + if (!autoEnable) { + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + } + + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + select_click_row(0); + + await TestUtils.waitForCondition( + () => OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "message should have encrypted icon" + ); + + // Clean up so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); + await OpenPGPTestUtils.removeKeyById(OpenPGPTestUtils.CAROL_KEY_ID); +} + +add_task( + async function testEncryptedRecipientKeyUnverifiedMessageCompositionAutoEncOff() { + await testEncryptedRecipientKeyUnverifiedMessageComposition( + false, + false, + false + ); + } +); + +add_task( + async function testEncryptedRecipientKeyUnverifiedMessageCompositionAutoEncOnAutoDisOff() { + await testEncryptedRecipientKeyUnverifiedMessageComposition( + true, + false, + false + ); + } +); + +add_task( + async function testEncryptedRecipientKeyUnverifiedMessageCompositionAutoEncOnAutoDisOn() { + await testEncryptedRecipientKeyUnverifiedMessageComposition( + true, + true, + false + ); + } +); + +/** + * Tests composition of a message to multiple recipients among whom, one key + * is missing, prompts the user. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedOneRecipientKeyNotAvailableMessageComposition( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example, carol@example.com", + "Compose Encrypted One Recipient Key Not Available Message Composition", + "This is an encrypted, one recipient key not available message test." + ); + await checkDonePromise; + + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + + let kaShown = BrowserTestUtils.waitForCondition( + () => composeWin.document.getElementById("keyAssistant").open, + "Timeout waiting for the #keyAssistant to be visible" + ); + + composeWin.goDoCommand("cmd_sendLater"); + await kaShown; + + await BrowserTestUtils.closeWindow(composeWin); +} + +add_task( + async function testEncryptedOneRecipientKeyNotAvailableMessageCompositionAutoEncOff() { + await testEncryptedOneRecipientKeyNotAvailableMessageComposition( + false, + false, + false + ); + } +); + +add_task( + async function testEncryptedOneRecipientKeyNotAvailableMessageCompositionAutoEncOnAutoDisOff() { + await testEncryptedOneRecipientKeyNotAvailableMessageComposition( + true, + false, + false + ); + } +); + +add_task( + async function testEncryptedOneRecipientKeyNotAvailableMessageCompositionAutoEncOnAutoDisOn() { + await testEncryptedOneRecipientKeyNotAvailableMessageComposition( + true, + true, + false + ); + } +); + +/** + * Tests composition of a message to multiple recipients among whom, one key + * is not accepted, prompts the user. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedOneRecipientKeyNotAcceptedMessageComposition( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/carol@example.com-0x3099ff1238852b9f-pub.asc" + ) + ), + OpenPGPTestUtils.ACCEPTANCE_UNDECIDED + ); + + for (let level of [ + OpenPGPTestUtils.ACCEPTANCE_UNDECIDED, + OpenPGPTestUtils.ACCEPTANCE_REJECTED, + ]) { + info(`Testing with acceptance level: "${level}"...`); + await OpenPGPTestUtils.updateKeyIdAcceptance( + OpenPGPTestUtils.CAROL_KEY_ID, + level + ); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example, carol@example.com", + "Compose Encrypted One Recipient Key Not Accepted Message Composition", + "This is an encrypted, one recipient key not accepted message test." + ); + await checkDonePromise; + + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + + let kaShown = BrowserTestUtils.waitForCondition( + () => composeWin.document.getElementById("keyAssistant").open, + "Timeout waiting for the #keyAssistant to be visible" + ); + + composeWin.goDoCommand("cmd_sendLater"); + await kaShown; + + await BrowserTestUtils.closeWindow(composeWin); + } + + await OpenPGPTestUtils.removeKeyById(OpenPGPTestUtils.CAROL_KEY_ID); +} + +add_task( + async function testEncryptedOneRecipientKeyNotAcceptedMessageCompositionAutoEncOff() { + await testEncryptedOneRecipientKeyNotAcceptedMessageComposition( + false, + false, + false + ); + } +); + +add_task( + async function testEncryptedOneRecipientKeyNotAcceptedMessageCompositionAutoEncOnAutoDisOff() { + await testEncryptedOneRecipientKeyNotAcceptedMessageComposition( + true, + false, + false + ); + } +); + +add_task( + async function testEncryptedOneRecipientKeyNotAcceptedMessageCompositionAutoEncOnAutoDisOn() { + await testEncryptedOneRecipientKeyNotAcceptedMessageComposition( + true, + true, + false + ); + } +); + +/** + * Tests composition of a message to multiple recipients among whom, one key + * is not verified, shows as encrypted in the Outbox. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedOneRecipientKeyUnverifiedMessageComposition( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/carol@example.com-0x3099ff1238852b9f-pub.asc" + ) + ), + OpenPGPTestUtils.ACCEPTANCE_UNVERIFIED + ); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example, carol@example.com", + "Compose Encrypted One Recipient Key Unverified Message", + "This is an encrypted, one recipient key unverified message test." + ); + await checkDonePromise; + + if (!autoEnable) { + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + } + + Assert.ok(composeWin.gSendEncrypted, "message encryption should be on"); + Assert.ok(composeWin.gSendSigned, "message signing should be on"); + + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + select_click_row(0); + + await TestUtils.waitForCondition( + () => OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "message should have encrypted icon" + ); + + // Clean up so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); + await OpenPGPTestUtils.removeKeyById(OpenPGPTestUtils.CAROL_KEY_ID); +} + +add_task( + async function testEncryptedOneRecipientKeyUnverifiedMessageCompositionAutoEncOff() { + await testEncryptedOneRecipientKeyUnverifiedMessageComposition( + false, + false, + false + ); + } +); + +add_task( + async function testEncryptedOneRecipientKeyUnverifiedMessageCompositionAutoEncOnAutoDisOff() { + await testEncryptedOneRecipientKeyUnverifiedMessageComposition( + true, + false, + false + ); + } +); + +add_task( + async function testEncryptedOneRecipientKeyUnverifiedMessageCompositionAutoEncOnAutoDisOn() { + await testEncryptedOneRecipientKeyUnverifiedMessageComposition( + true, + true, + false + ); + } +); + +/** + * Tests composing a reply to an encrypted message is encrypted by default. + * + * @param {boolean} autoEnable - set pref mail.e2ee.auto_enable to this value + * @param {boolean} autoDisable - set pref mail.e2ee.auto_disable to this value + * @param {boolean} notifyOnDisable - set pref mail.e2ee.notify_on_auto_disable + * to this value + */ +async function testEncryptedMessageReplyIsEncrypted( + autoEnable, + autoDisable, + notifyOnDisable +) { + setAutoPrefs(autoEnable, autoDisable, notifyOnDisable); + + await be_in_folder(gDrafts); + let mc = await open_message_from_file( + new FileUtils.File( + getTestFilePath( + "../data/eml/signed-by-0xfbfcc82a015e7330-encrypted-to-0xf231550c4f47e38e.eml" + ) + ) + ); + + let cwc = open_compose_with_reply(mc); + close_window(mc); + + let replyWindow = cwc.window; + + await save_compose_message(replyWindow); + close_compose_window(cwc); + + await TestUtils.waitForCondition( + () => gDrafts.getTotalMessages(true) > 0, + "message should be saved to drafts folder" + ); + + await be_in_folder(gDrafts); + select_click_row(0); + + await TestUtils.waitForCondition( + () => OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "message should have encrypted icon" + ); + + // Delete the outgoing message. + press_delete(); +} + +add_task( + async function testEncryptedMessageReplyIsEncryptedAutoEncOnAutoDisOff() { + await testEncryptedMessageReplyIsEncrypted(true, false, false); + } +); + +add_task( + async function testEncryptedMessageReplyIsEncryptedAutoEncOnAutoDisOn() { + await testEncryptedMessageReplyIsEncrypted(true, true, false); + } +); + +registerCleanupFunction(function tearDown() { + clearAutoPrefs(); + MailServices.accounts.removeIncomingServer(bobAcct.incomingServer, true); + MailServices.accounts.removeAccount(bobAcct, true); +}); diff --git a/comm/mail/test/browser/openpgp/composition/browser_composeSigned.js b/comm/mail/test/browser/openpgp/composition/browser_composeSigned.js new file mode 100644 index 0000000000..a2a4a4b21d --- /dev/null +++ b/comm/mail/test/browser/openpgp/composition/browser_composeSigned.js @@ -0,0 +1,423 @@ +/* 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 for OpenPGP signed message composition. + */ + +"use strict"; + +const { + assert_selected_and_displayed, + be_in_folder, + get_about_message, + get_special_folder, + select_click_row, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +const { open_compose_new_mail, get_msg_source, setup_msg_contents } = + ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm"); +const { OpenPGPTestUtils } = ChromeUtils.import( + "resource://testing-common/mozmill/OpenPGPTestUtils.jsm" +); +const { EnigmailPersistentCrypto } = ChromeUtils.import( + "chrome://openpgp/content/modules/persistentCrypto.jsm" +); + +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +let bobAcct; +let bobIdentity; +let initialKeyIdPref = ""; +let gOutbox; + +let aboutMessage = get_about_message(); + +async function waitCheckEncryptionStateDone(win) { + return BrowserTestUtils.waitForEvent( + win.document, + "encryption-state-checked" + ); +} + +/** + * Setup a mail account with a private key and import the public key for the + * receiver. + */ +add_setup(async function () { + bobAcct = MailServices.accounts.createAccount(); + bobAcct.incomingServer = MailServices.accounts.createIncomingServer( + "bob", + "openpgp.example", + "imap" + ); + bobIdentity = MailServices.accounts.createIdentity(); + bobIdentity.email = "bob@openpgp.example"; + bobAcct.addIdentity(bobIdentity); + + let [id] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/bob@openpgp.example-0xfbfcc82a015e7330-secret.asc" + ) + ) + ); + + Assert.ok(id, "private key id received"); + + initialKeyIdPref = bobIdentity.getUnicharAttribute("openpgp_key_id"); + bobIdentity.setUnicharAttribute("openpgp_key_id", id.split("0x").join("")); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/alice@openpgp.example-0xf231550c4f47e38e-pub.asc" + ) + ) + ); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/carol@example.com-0x3099ff1238852b9f-pub.asc" + ) + ) + ); + + gOutbox = await get_special_folder(Ci.nsMsgFolderFlags.Queue); +}); + +/** + * Tests composition of a message that is signed only shows as signed in the + * Outbox. + */ +add_task(async function testSignedMessageComposition() { + let autocryptPrefName = "mail.identity.default.sendAutocryptHeaders"; + Services.prefs.setBoolPref(autocryptPrefName, true); + + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Signed Message", + "This is a signed message composition test." + ); + + await OpenPGPTestUtils.toggleMessageSigning(composeWin); + await OpenPGPTestUtils.toggleMessageKeyAttachment(composeWin); + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + let msg = select_click_row(0); + assert_selected_and_displayed(0); + let src = await get_msg_source(msg); + let lines = src.split("\n"); + + Assert.ok( + lines.some( + line => line.trim() == "Autocrypt: addr=bob@openpgp.example; keydata=" + ), + "Correct Autocrypt header found" + ); + + Assert.ok( + OpenPGPTestUtils.hasSignedIconState(aboutMessage.document, "ok"), + "message has signed icon" + ); + + Assert.equal( + aboutMessage.document.querySelector("#attachmentList").itemChildren.length, + 0, + "no keys attached to message" + ); + + Assert.ok( + !OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "encrypted icon is not displayed" + ); + + // Delete the message so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); + // Restore pref to original value + Services.prefs.clearUserPref(autocryptPrefName); +}); + +/** + * Tests composition of a message that is signed only with, public key attachment + * enabled, shows as signed in the Outbox. + */ +add_task(async function testSignedMessageWithKeyComposition() { + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Signed Message With Key", + "This is a signed message with key composition test." + ); + + await OpenPGPTestUtils.toggleMessageSigning(composeWin); + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + select_click_row(0); + assert_selected_and_displayed(0); + + Assert.ok( + OpenPGPTestUtils.hasSignedIconState(aboutMessage.document, "ok"), + "message has signed icon" + ); + + let attachmentList = aboutMessage.document.querySelector("#attachmentList"); + + Assert.equal( + attachmentList.itemChildren.length, + 1, + "message has one attachment" + ); + + Assert.ok( + attachmentList + .getItemAtIndex(0) + .attachment.name.includes(OpenPGPTestUtils.BOB_KEY_ID), + "attachment name contains Bob's key id" + ); + + Assert.ok( + !OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "encrypted icon is not displayed" + ); + + // Delete the message so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); +}); + +/* +This comment documents Carol's and Alice's keys encoded as autocrypt +headers. + +Autocrypt-Gossip: addr=alice@openpgp.example; keydata= + xjMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/Ub7O1u13N + JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+wpAEExYIADgCGwMFCwkI + BwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXaWfOgAKCRDy + MVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnOdypvbm+QtXZqth9rvwD9HcDC0tC+PHAs + O7OTh1S1TC9RiJsvawAfCPaQZoed8gLOOARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzg + qbXCpDDYMiKRVitCsy203x3sE9+eviIDAQgHwngEGBYIACAWIQTrhbtfozp14V6UTmPyMVUM + T0fjjgUCXEcE6QIbDAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW + 4xN80fsn0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE= +Autocrypt-Gossip: addr=carol@example.com; keydata= + xsFNBF9GZTQBEACjK8Db1095rU74k/RwLhmp9rmFBZR6qyEHANlHSVwqARxa4aJPaNoLbqNP + efuFg9ib3J0rKcZfqgnqC4usPVSTdmC4w0MdmHvh+1tUoXcxnrjYNRRbP+lC7zaLRRnEEioi + mC0Mkh+ow1u4F2QFBjwcV9bD7i0T1DRfR5k5kh3kcaYFnGnwMjwjJzLtvu3OZbXYsofCw789 + 0TP4LkqLEQVOw1OrxBnRd5QNBVojcQi6rnKOQ7AUBGRKSXI3QVrbP+x1oImXpQSqIyaRFbtx + 57QafDdkyHBEfChO9X96BtMndyry8XgYtcgmwKKWg8Js4TJgghus6Sng5dA7/87nRf/9//Np + tXh9mdW3AiHsqb+tBu7NJGk6pAPL4fUjXILjcm5ZXdlUeFVLmYmqTiOJcGFbqHEBGcwLKPob + a2JsBEpnRj0ZEmo2khT+9tXJK3FUANc4w/QfxTXMwV17yYvocDPEBkoKcbxE8b2sSK/L7Vi+ + h21XX6fA6B3zKFQ3hetFvOjEGTCkhFD9asL8KnwQdJmYo4Bd45AVoMZFxBxpmuo9MxPdiF2A + GbKHgrKpqDw2pUfelFwMZIVQ4Ya1wdtLe8gEJAMq6YnuuQcq+jjGKubNRywld7xXIsxJCpHt + qbCQM9P+gqp1VDBnbsk4xGX0HgILXF2JfyceGMGy1Lku0QA+ywARAQABzRlDYXJvbCA8Y2Fy + b2xAZXhhbXBsZS5jb20+wsGJBBMBCAAzFiEEuPL29L060/gtxEaDMJn/EjiFK58FAl9GZTUC + GwMFCwkIBwIGFQgJCgsCBRYCAwEAAAoJEDCZ/xI4hSufjB0P/0+yaZknO8dS5o7Gp1ZuJwh6 + +vgTGWrTxcBtsU1JR4BFobPKtMmw45FKsNIiK+AQ7ExCtqumGoTJ6hlclBFMlDQyyCxJG/Zp + PdrFUFyg6JUVf05/LWsd4Fwy/hQY1ha8R81QinSHqv9DJk6fKZG2rz7YUE47LFfjugbwUj9y + 8naTxj823Vm6v36J2wgl/1/PHoZTwi3vQRA70SoIDt4tSjqBzuclt2k/zlkJmOpBYtQb+xGw + pfnh2gBJdYurLwJO9rQlzYjy/+1qB0CZsE95WlkTrqQw8V5S6ULcnyACbETdF5HF/geHL367 + p/iWULD907E4DJlQBOWjY6fdsJIBj96NfQiG+cXYTNGqaB/FgW8jyoS9vyg4PDOr0nGHLvzP + w7xTDUkuoJiWXMJ9kDYTZ+MsWreA885i1JSE32CsqqP3+kI7XQD3d3T3pIPhKOo0/bzbLY6y + WBXh809Ovi9fMxaZkrlrmA3lFcY+FbzDjZB+UYOXDB6TRu1jvISVMiXnYf4X21xWyl8AWv1q + ANMSXFKUwBSR88I06QZiJBmm9wHcyVtK/Hb6pgH10LydZvIfRDLrDBc2z31rswjNj9UhNp0Q + fGdNz/gXdxc8HP7Pf4kHkjIxLrWUNlDpYddX+iz1Z//VY9h2XTmSail5pMyyXdiGm90AGfVh + IcaOoeKK9UslzsFNBF9GZTUBEADWPef8E4OUoxU+vhwCxy/4nDfxzV4ZMFYkqp8QgpLzTVgT + v6xGVHFx/waNjwR6G34tD0aYhkDrumv9QsMdiQnMw9pLAoc3bnIkL8LkXnS8fVeiuzkXd4lg + vpxFlce7KYuXos9Ew7Nm2tOx4ovoygFikjliFTKn+QOVJoTr4pxJL9RdzYQ/pV/DI/fc2cmR + Wy0uivP+F+LBtYW6ZOMY1aXzsJEvun2i5ZxV2jqNDhXpD3m6/Y/28WItKbmT80hvTivxO2DS + Q1kqNcwB8Z0XWZJoz6iyYUu27dKB0L4S/x4UASlC6J2Db8bIL3Tdhuy+N0BN8sS1TDWb7Oi1 + Ad8huVxfrRSyOYj4fkksvAEgDEDH6JEvJBU3CGQtfXCoX6d64db2cGp85GDfNHTREJ0mbRjL + AKL1RKrcKOG1790OZU2veF5qiN2eN08OLfJURL8+P4+mDWbaOcZasqNrg3YhYcPX3ZZzKfEI + vvTOdqMk00JU3zaUZhJvGOR9tJ27NBTrCEIOHz7yzOJltTDjdfNZNLqSYFp08+vR/IjSDv8h + l6PRjkomkbfdPdwPczKS0dG9Cf8cU+NZQrEgE0Un4tvb7p55j9R5OVgHUACLFTlDIRV4veD5 + RnM2hUFRtBONymXEDjoPGZXaHhv16MckFpZ1IEAkMIZ3Ti/NIZcS7IA9jRgBUQARAQABwsF2 + BBgBCAAgFiEEuPL29L060/gtxEaDMJn/EjiFK58FAl9GZTYCGwwACgkQMJn/EjiFK5/Q3hAA + mzMu7EOeWG0xAHAQ4b/ocCSlZqg/MSf6kJIkzUxdnX9T/ylEmrS8cEg5mdJMQMVvCecyDpNK + 9MgJPV7MTnR6x/4qgdVUTtknd6W7RrQ7Oai150nMH5U9M8GrFtbQjc/fOw17agoT06ZGV4um + IK41IIGwQZ2/Z/cElHkQZll9//hYS8/E8xOBlweVxsMZhfcLFrbx2hC2osRt0vMlGnYSnv29 + ligVG+2PwwnHXB6Tn7eslzoowY78ANCTvA6Rc6zR+RIs/CIiaDNgWCRBJcueZVpA+JkyL6Km + C+JiiF6Hsm07DDDjgLVJ0s660GNe8sWw4IZ8wpvYq1goqXLu+CMqbCsBrEDwfguClxGSQnLw + AUIVxuyKprToLJ6hmuubsVcv9fzf/GoYFnT9hge1YZpptKi/zrQqy2CZuSZEHWpUZcwPE3Ow + qbHKty3UhZPJU50kmEOd/UQNJYNWxxxx5593X96jLLDOxm5M5jNNRvGZPgn8RbA1e7VC2XFg + V2KGJHq/gxCpwkWs8+0sYUtcFuu+RQWTKbJpFcxfAIEDKS+fyLRAFdYqUA3yQIA1UYco10l8 + RYPLY0+IXiArqjql8+k8PBT0U4P59lfcKlY2GaJe4aoWLPOdNZAJgLzoxd5zgnz0vI3sn+3v + meCtpxz2PoYBJfxGPEzu9xTLV6k9wSVTCgE= +*/ + +/** + * Tests composition of a signed, encrypted message, for two recipients, + * is shown as signed and encrypted in the Outbox, and has the + * Autocrypt-Gossip headers. + */ +add_task(async function testSignedEncryptedMessageComposition() { + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example, carol@example.com", + "Compose Signed Encrypted Message", + "This is a signed, encrypted message composition test." + ); + await checkDonePromise; + + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + + await OpenPGPTestUtils.toggleMessageKeyAttachment(composeWin); + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + let encryptedMsg = select_click_row(0); + assert_selected_and_displayed(0); + + Assert.ok( + OpenPGPTestUtils.hasSignedIconState(aboutMessage.document, "ok"), + "message has signed icon" + ); + + Assert.ok( + OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "message has encrypted icon" + ); + + Assert.equal( + aboutMessage.document.querySelector("#attachmentList").itemChildren.length, + 0, + "no keys attached to message" + ); + + // Check that the gossip headers are inside the encrypted message. + // To check that easily, we decrypt the message to another folder, + // and then get its source. + + // moving to decrypted message in same folder (deleting original) + await EnigmailPersistentCrypto.cryptMessage( + encryptedMsg, + gOutbox.URI, + true, + null + ); + + let msg = await select_click_row(0); + let src = await get_msg_source(msg); + let lines = src.split("\r\n"); + + // As a sanity check, we check that the header line, plus the first + // and last lines of the keydata are present. + let expectedGossipLines = [ + "Autocrypt-Gossip: addr=alice@openpgp.example; keydata=", + " xjMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/Ub7O1u13N", + " 4xN80fsn0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=", + "Autocrypt-Gossip: addr=carol@example.com; keydata=", + " xsFNBF9GZTQBEACjK8Db1095rU74k/RwLhmp9rmFBZR6qyEHANlHSVwqARxa4aJPaNoLbqNP", + " meCtpxz2PoYBJfxGPEzu9xTLV6k9wSVTCgE=", + ]; + + for (let egl of expectedGossipLines) { + Assert.ok( + lines.some(line => line == egl), + "The following Autocrypt-Gossip header line was found: " + egl + ); + } + + // Delete the message so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); +}); + +/** + * Tests composition of a signed, encrypted, message with public key attachment + * enabled, is shown signed, encrypted in the Outbox. + */ +add_task(async function testSignedEncryptedMessageWithKeyComposition() { + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Signed Encrypted Message With Key", + "This is a signed, encrypted message with key composition test." + ); + await checkDonePromise; + + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + select_click_row(0); + assert_selected_and_displayed(0); + + Assert.ok( + OpenPGPTestUtils.hasSignedIconState(aboutMessage.document, "ok"), + "message has signed icon" + ); + + Assert.ok( + OpenPGPTestUtils.hasEncryptedIconState(aboutMessage.document, "ok"), + "message has encrypted icon" + ); + + let attachmentList = aboutMessage.document.querySelector("#attachmentList"); + + Assert.equal( + attachmentList.itemChildren.length, + 1, + "message has one attachment" + ); + + Assert.ok( + attachmentList + .getItemAtIndex(0) + .attachment.name.includes(OpenPGPTestUtils.BOB_KEY_ID), + "attachment name contains Bob's key id" + ); + + // Delete the message so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); +}); + +registerCleanupFunction(async function tearDown() { + bobIdentity.setUnicharAttribute("openpgp_key_id", initialKeyIdPref); + await OpenPGPTestUtils.removeKeyById("0xfbfcc82a015e7330", true); + MailServices.accounts.removeIncomingServer(bobAcct.incomingServer, true); + MailServices.accounts.removeAccount(bobAcct, true); +}); diff --git a/comm/mail/test/browser/openpgp/composition/browser_composeSigned2.js b/comm/mail/test/browser/openpgp/composition/browser_composeSigned2.js new file mode 100644 index 0000000000..608afea82c --- /dev/null +++ b/comm/mail/test/browser/openpgp/composition/browser_composeSigned2.js @@ -0,0 +1,213 @@ +/* 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 for OpenPGP signed message composition, + * when OpenPGP passphrases are in use. + */ + +"use strict"; + +const { + assert_selected_and_displayed, + be_in_folder, + get_about_message, + get_special_folder, + select_click_row, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +const { open_compose_new_mail, get_msg_source, setup_msg_contents } = + ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm"); +const { OpenPGPTestUtils } = ChromeUtils.import( + "resource://testing-common/mozmill/OpenPGPTestUtils.jsm" +); + +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +let bobAcct; +let gOutbox; +let kylieAcct; + +let aboutMessage = get_about_message(); + +/** + * Setup a mail account with a private key and import the public key for the + * receiver. + */ +add_setup(async function () { + bobAcct = MailServices.accounts.createAccount(); + bobAcct.incomingServer = MailServices.accounts.createIncomingServer( + "bob", + "openpgp.example", + "imap" + ); + let bobIdentity = MailServices.accounts.createIdentity(); + bobIdentity.email = "bob@openpgp.example"; + bobAcct.addIdentity(bobIdentity); + + let [id] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/bob@openpgp.example-0xfbfcc82a015e7330-secret-with-pp.asc" + ) + ), + OpenPGPTestUtils.ACCEPTANCE_PERSONAL, + "bob-passphrase", + true + ); + + Assert.ok(id, "private key id received"); + + let initialKeyIdPref = bobIdentity.getUnicharAttribute("openpgp_key_id"); + bobIdentity.setUnicharAttribute("openpgp_key_id", id.split("0x").join("")); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/alice@openpgp.example-0xf231550c4f47e38e-pub.asc" + ) + ) + ); + + gOutbox = await get_special_folder(Ci.nsMsgFolderFlags.Queue); + + kylieAcct = MailServices.accounts.createAccount(); + kylieAcct.incomingServer = MailServices.accounts.createIncomingServer( + "kylie", + "example.com", + "imap" + ); + let kylieIdentity = MailServices.accounts.createIdentity(); + kylieIdentity.email = "kylie@example.com"; + kylieAcct.addIdentity(kylieIdentity); + + let [id2] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/kylie-0x1AABD9FAD1E411DD-secret-subkeys.asc" + ) + ), + OpenPGPTestUtils.ACCEPTANCE_PERSONAL, + "kylie-passphrase", + false + ); + + Assert.ok(id2, "private key id received"); + kylieIdentity.setUnicharAttribute("openpgp_key_id", id2.split("0x").join("")); + + registerCleanupFunction(async function tearDown() { + bobIdentity.setUnicharAttribute("openpgp_key_id", initialKeyIdPref); + await OpenPGPTestUtils.removeKeyById("0xfbfcc82a015e7330", true); + MailServices.accounts.removeIncomingServer(bobAcct.incomingServer, true); + MailServices.accounts.removeAccount(bobAcct, true); + await OpenPGPTestUtils.removeKeyById("0x1AABD9FAD1E411DD", true); + MailServices.accounts.removeIncomingServer(kylieAcct.incomingServer, true); + MailServices.accounts.removeAccount(kylieAcct, true); + }); +}); + +/** + * Tests composition of a signed message is shown as signed in the Outbox. + */ +add_task(async function testSignedMessageComposition2() { + await be_in_folder(bobAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Signed Message", + "This is a signed message composition test." + ); + + await OpenPGPTestUtils.toggleMessageSigning(composeWin); + await OpenPGPTestUtils.toggleMessageKeyAttachment(composeWin); + + let passPromptPromise = BrowserTestUtils.promiseAlertDialogOpen(); + let sendMessageCompletePromise = sendMessage(composeWin); + + let ppWin = await passPromptPromise; + + // We'll enter a wrong pp, so we expect another prompt + let passPromptPromise2 = BrowserTestUtils.promiseAlertDialogOpen(); + + ppWin.document.getElementById("password1Textbox").value = "WRONG-passphrase"; + ppWin.document.querySelector("dialog").getButton("accept").click(); + + let ppWin2 = await passPromptPromise2; + + ppWin2.document.getElementById("password1Textbox").value = "bob-passphrase"; + ppWin2.document.querySelector("dialog").getButton("accept").click(); + + await sendMessageCompletePromise; + + await be_in_folder(gOutbox); + select_click_row(0); + assert_selected_and_displayed(0); + + Assert.ok( + OpenPGPTestUtils.hasSignedIconState(aboutMessage.document, "ok"), + "message should have signed icon" + ); + + Assert.equal( + aboutMessage.document.querySelector("#attachmentList").itemChildren.length, + 0, + "there should be no keys attached to message" + ); + + // Delete the message so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); +}); + +/** + * Tests composition of a signed message is shown as signed in the Outbox, + * with a key that has an offline primary key. Ensure the subkeys were + * imported correctly and are no longer protected by a passphrase + * (ensure import remove the passphrase protection and switched them + * to use automatic protection). + */ +add_task(async function testSignedMessageComposition3() { + await be_in_folder(kylieAcct.incomingServer.rootFolder); + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Signed Message", + "This is a signed message composition test." + ); + + await OpenPGPTestUtils.toggleMessageSigning(composeWin); + await OpenPGPTestUtils.toggleMessageKeyAttachment(composeWin); + await sendMessage(composeWin); + + await be_in_folder(gOutbox); + select_click_row(0); + assert_selected_and_displayed(0); + + Assert.ok( + OpenPGPTestUtils.hasSignedIconState(aboutMessage.document, "ok"), + "message should have signed icon" + ); + + Assert.equal( + aboutMessage.document.querySelector("#attachmentList").itemChildren.length, + 0, + "there should be no keys attached to message" + ); + + // Delete the message so other tests work. + EventUtils.synthesizeKey("VK_DELETE"); +}); diff --git a/comm/mail/test/browser/openpgp/composition/browser_composeSwitchIdentity.js b/comm/mail/test/browser/openpgp/composition/browser_composeSwitchIdentity.js new file mode 100644 index 0000000000..fdcfecf087 --- /dev/null +++ b/comm/mail/test/browser/openpgp/composition/browser_composeSwitchIdentity.js @@ -0,0 +1,821 @@ +/* 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 for OpenPGP encrypted message composition. + */ + +"use strict"; + +const { + open_message_from_file, + be_in_folder, + get_special_folder, + select_click_row, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +const { open_compose_new_mail, setup_msg_contents } = ChromeUtils.import( + "resource://testing-common/mozmill/ComposeHelpers.jsm" +); +const { click_menus_in_sequence, close_window } = ChromeUtils.import( + "resource://testing-common/mozmill/WindowHelpers.jsm" +); +const { OpenPGPTestUtils } = ChromeUtils.import( + "resource://testing-common/mozmill/OpenPGPTestUtils.jsm" +); + +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +let bobAcct; +let bobIdentity; +let plainIdentity; +let gOutbox; + +// Used in some of the tests to verify key status display. +let l10n = new Localization(["messenger/openpgp/composeKeyStatus.ftl"]); + +/** + * Closes a window with a <dialog> element by calling the acceptDialog(). + * + * @param {Window} win + */ +async function closeDialog(win) { + let closed = BrowserTestUtils.domWindowClosed(win); + win.document.documentElement.querySelector("dialog").acceptDialog(); + await closed; +} + +async function waitCheckEncryptionStateDone(win) { + return BrowserTestUtils.waitForEvent( + win.document, + "encryption-state-checked" + ); +} + +/** + * Setup a mail account with a private key and import the public key for the + * receiver. + */ +add_setup(async function () { + // Encryption makes the compose process a little longer. + requestLongerTimeout(5); + + bobAcct = MailServices.accounts.createAccount(); + bobAcct.incomingServer = MailServices.accounts.createIncomingServer( + "bob", + "openpgp.example", + "imap" + ); + bobIdentity = MailServices.accounts.createIdentity(); + bobIdentity.email = "bob@openpgp.example"; + bobAcct.addIdentity(bobIdentity); + + plainIdentity = MailServices.accounts.createIdentity(); + plainIdentity.email = "bob+plain@openpgp.example"; + bobAcct.addIdentity(plainIdentity); + + let [id] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/bob@openpgp.example-0xfbfcc82a015e7330-secret.asc" + ) + ) + ); + + Assert.ok(id, "private key id received"); + bobIdentity.setUnicharAttribute("openpgp_key_id", id.split("0x").join("")); + + await OpenPGPTestUtils.importPublicKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/alice@openpgp.example-0xf231550c4f47e38e-pub.asc" + ) + ) + ); + + gOutbox = await get_special_folder(Ci.nsMsgFolderFlags.Queue); +}); + +async function testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity +) { + await be_in_folder(bobAcct.incomingServer.rootFolder); + + bobIdentity.encryptionPolicy = prefEncryptionPolicy; + bobIdentity.signMail = prefSignMail; + bobIdentity.attachPgpKey = prefAttachPgpKey; + bobIdentity.protectSubject = prefProtectSubject; + + let cwc = open_compose_new_mail(); + let composeWin = cwc.window; + + // setup_msg_contents will trigger checkEncryptionState. + let checkDonePromise = waitCheckEncryptionStateDone(composeWin); + setup_msg_contents( + cwc, + "alice@openpgp.example", + "Compose Message", + "This is a message." + ); + await checkDonePromise; + + Assert.equal(composeWin.gSendEncrypted, expectSendEncrypted); + Assert.equal(composeWin.gSendSigned, expectSendSigned); + Assert.equal(composeWin.gAttachMyPublicPGPKey, expectAttachMyPublicPGPKey); + Assert.equal(composeWin.gEncryptSubject, expectEncryptSubject); + + if (testToggle) { + if (testToggle == "encrypt") { + // This toggle will trigger checkEncryptionState(), request that + // an event will be sent after the next call to checkEncryptionState + // has completed. + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + await OpenPGPTestUtils.toggleMessageEncryption(composeWin); + await checkDonePromise; + } else if (testToggle == "sign") { + await OpenPGPTestUtils.toggleMessageSigning(composeWin); + } else if (testToggle == "encrypt-subject") { + await OpenPGPTestUtils.toggleMessageEncryptSubject(composeWin); + } else if (testToggle == "attach-key") { + await OpenPGPTestUtils.toggleMessageKeyAttachment(composeWin); + } else { + Assert.ok(false, "test provides allowed toggle parameter"); + } + + Assert.equal(composeWin.gSendEncrypted, expectSendEncrypted2AfterToggle); + Assert.equal(composeWin.gSendSigned, expectSendSigned2AfterToggle); + Assert.equal( + composeWin.gAttachMyPublicPGPKey, + expectAttachMyPublicPGPKey2AfterToggle + ); + Assert.equal(composeWin.gEncryptSubject, expectEncryptSubject2AfterToggle); + } + + if (switchIdentity) { + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + + EventUtils.synthesizeMouseAtCenter( + cwc.window.document.getElementById("msgIdentity"), + {}, + cwc.window.document.getElementById("msgIdentity").ownerGlobal + ); + await click_menus_in_sequence( + cwc.window.document.getElementById("msgIdentityPopup"), + [{ identitykey: plainIdentity.key }] + ); + + await checkDonePromise; + + Assert.equal( + composeWin.gSendEncrypted, + expectSendEncrypted3GoneToPlainIdentity + ); + Assert.equal(composeWin.gSendSigned, expectSendSigned3GoneToPlainIdentity); + Assert.equal( + composeWin.gAttachMyPublicPGPKey, + expectAttachMyPublicPGPKey3GoneToPlainIdentity + ); + Assert.equal( + composeWin.gEncryptSubject, + expectEncryptSubject3GoneToPlainIdentity + ); + + checkDonePromise = waitCheckEncryptionStateDone(composeWin); + + EventUtils.synthesizeMouseAtCenter( + cwc.window.document.getElementById("msgIdentity"), + {}, + cwc.window.document.getElementById("msgIdentity").ownerGlobal + ); + await click_menus_in_sequence( + cwc.window.document.getElementById("msgIdentityPopup"), + [{ identitykey: bobIdentity.key }] + ); + + await checkDonePromise; + + Assert.equal( + composeWin.gSendEncrypted, + expectSendEncrypted4GoneToOrigIdentity + ); + Assert.equal(composeWin.gSendSigned, expectSendSigned4GoneToOrigIdentity); + Assert.equal( + composeWin.gAttachMyPublicPGPKey, + expectAttachMyPublicPGPKey4GoneToOrigIdentity + ); + Assert.equal( + composeWin.gEncryptSubject, + expectEncryptSubject4GoneToOrigIdentity + ); + } + + await BrowserTestUtils.closeWindow(composeWin); + await TestUtils.waitForCondition( + () => document.hasFocus(), + "waiting for focus to return to the main window" + ); +} + +/** + * Each function below tests a specific identity e2ee configuration + * (see initial variables named pref*), + * then opening a composer window based on those prefs, + * then optionally toggling an e2ee flag in composer window, + * then switching to a default "from" identity (no e2ee configured), + * then switching back to the initial identity, + * and checks that the resulting message flags (as seen in variables) + * at each step are as expected. + */ + +add_task(async function testMsgComp1() { + let prefEncryptionPolicy = 0; // default encryption: off + let prefSignMail = false; // sign unencrypted messages: off + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = false; + let expectSendSigned = false; + let expectAttachMyPublicPGPKey = false; + let expectEncryptSubject = false; + let testToggle = null; + let expectSendEncrypted2AfterToggle = undefined; + let expectSendSigned2AfterToggle = undefined; + let expectAttachMyPublicPGPKey2AfterToggle = undefined; + let expectEncryptSubject2AfterToggle = undefined; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = false; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = false; + let expectSendEncrypted4GoneToOrigIdentity = false; + let expectSendSigned4GoneToOrigIdentity = false; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = false; + let expectEncryptSubject4GoneToOrigIdentity = false; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp1b() { + let prefEncryptionPolicy = 0; // default encryption: off + let prefSignMail = false; // sign unencrypted messages: off + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = false; + let expectSendSigned = false; + let expectAttachMyPublicPGPKey = false; + let expectEncryptSubject = false; + let testToggle = "sign"; + let expectSendEncrypted2AfterToggle = false; + let expectSendSigned2AfterToggle = true; + let expectAttachMyPublicPGPKey2AfterToggle = true; + let expectEncryptSubject2AfterToggle = false; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = false; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = false; + let expectSendEncrypted4GoneToOrigIdentity = false; + let expectSendSigned4GoneToOrigIdentity = false; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = false; + let expectEncryptSubject4GoneToOrigIdentity = false; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp2() { + let prefEncryptionPolicy = 0; // default encryption: off + let prefSignMail = true; // sign unencrypted messages: on + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = false; + let expectSendSigned = true; + let expectAttachMyPublicPGPKey = true; + let expectEncryptSubject = false; + let testToggle = null; + let expectSendEncrypted2AfterToggle = undefined; + let expectSendSigned2AfterToggle = undefined; + let expectAttachMyPublicPGPKey2AfterToggle = undefined; + let expectEncryptSubject2AfterToggle = undefined; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = false; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = false; + let expectSendEncrypted4GoneToOrigIdentity = false; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = true; + let expectEncryptSubject4GoneToOrigIdentity = false; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp2b() { + let prefEncryptionPolicy = 0; // default encryption: off + let prefSignMail = true; // sign unencrypted messages: on + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = false; + let expectSendSigned = true; + let expectAttachMyPublicPGPKey = true; + let expectEncryptSubject = false; + let testToggle = "attach-key"; + let expectSendEncrypted2AfterToggle = false; + let expectSendSigned2AfterToggle = true; + let expectAttachMyPublicPGPKey2AfterToggle = false; + let expectEncryptSubject2AfterToggle = false; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = false; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = false; + let expectSendEncrypted4GoneToOrigIdentity = false; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = false; + let expectEncryptSubject4GoneToOrigIdentity = false; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp3() { + let prefEncryptionPolicy = 2; // default encryption: on (require) + let prefSignMail = false; // sign unencrypted messages: off + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = true; + let expectSendSigned = true; + let expectAttachMyPublicPGPKey = true; + let expectEncryptSubject = true; + let testToggle = null; + let expectSendEncrypted2AfterToggle = undefined; + let expectSendSigned2AfterToggle = undefined; + let expectAttachMyPublicPGPKey2AfterToggle = undefined; + let expectEncryptSubject2AfterToggle = undefined; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = true; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = true; + let expectSendEncrypted4GoneToOrigIdentity = true; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = true; + let expectEncryptSubject4GoneToOrigIdentity = true; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp3b() { + let prefEncryptionPolicy = 2; // default encryption: on (require) + let prefSignMail = false; // sign unencrypted messages: off + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = true; + let expectSendSigned = true; + let expectAttachMyPublicPGPKey = true; + let expectEncryptSubject = true; + let testToggle = "encrypt-subject"; + let expectSendEncrypted2AfterToggle = true; + let expectSendSigned2AfterToggle = true; + let expectAttachMyPublicPGPKey2AfterToggle = true; + let expectEncryptSubject2AfterToggle = false; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = true; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = false; + let expectSendEncrypted4GoneToOrigIdentity = true; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = true; + let expectEncryptSubject4GoneToOrigIdentity = false; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp4() { + let prefEncryptionPolicy = 2; // default encryption: on (require) + let prefSignMail = true; // sign unencrypted messages: on + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = true; + let expectSendSigned = true; + let expectAttachMyPublicPGPKey = true; + let expectEncryptSubject = true; + let testToggle = null; + let expectSendEncrypted2AfterToggle = undefined; + let expectSendSigned2AfterToggle = undefined; + let expectAttachMyPublicPGPKey2AfterToggle = undefined; + let expectEncryptSubject2AfterToggle = undefined; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = true; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = true; + let expectSendEncrypted4GoneToOrigIdentity = true; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = true; + let expectEncryptSubject4GoneToOrigIdentity = true; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp4b() { + let prefEncryptionPolicy = 2; // default encryption: on (require) + let prefSignMail = true; // sign unencrypted messages: on + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = true; + let expectSendSigned = true; + let expectAttachMyPublicPGPKey = true; + let expectEncryptSubject = true; + let testToggle = "attach-key"; + let expectSendEncrypted2AfterToggle = true; + let expectSendSigned2AfterToggle = true; + let expectAttachMyPublicPGPKey2AfterToggle = false; + let expectEncryptSubject2AfterToggle = true; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = true; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = true; + let expectSendEncrypted4GoneToOrigIdentity = true; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = false; + let expectEncryptSubject4GoneToOrigIdentity = true; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp5() { + let prefEncryptionPolicy = 2; // default encryption: on (require) + let prefSignMail = false; // sign unencrypted messages: off + let prefAttachPgpKey = false; // attach key to signed messages: off + let prefProtectSubject = false; // encrypt subject of encrypted message: off + + let expectSendEncrypted = true; + let expectSendSigned = true; + let expectAttachMyPublicPGPKey = false; + let expectEncryptSubject = false; + let testToggle = null; + let expectSendEncrypted2AfterToggle = undefined; + let expectSendSigned2AfterToggle = undefined; + let expectAttachMyPublicPGPKey2AfterToggle = undefined; + let expectEncryptSubject2AfterToggle = undefined; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = true; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = true; + let expectSendEncrypted4GoneToOrigIdentity = true; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = false; + let expectEncryptSubject4GoneToOrigIdentity = false; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp6() { + let prefEncryptionPolicy = 0; // default encryption: off + let prefSignMail = false; // sign unencrypted messages: off + let prefAttachPgpKey = true; // attach key to signed messages: on + let prefProtectSubject = true; // encrypt subject of encrypted message: on + + let expectSendEncrypted = false; + let expectSendSigned = false; + let expectAttachMyPublicPGPKey = false; + let expectEncryptSubject = false; + let testToggle = "encrypt"; + let expectSendEncrypted2AfterToggle = true; + let expectSendSigned2AfterToggle = true; + let expectAttachMyPublicPGPKey2AfterToggle = true; + let expectEncryptSubject2AfterToggle = true; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = true; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = true; + let expectSendEncrypted4GoneToOrigIdentity = true; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = true; + let expectEncryptSubject4GoneToOrigIdentity = true; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +add_task(async function testMsgComp7() { + let prefEncryptionPolicy = 0; // default encryption: off + let prefSignMail = true; // sign unencrypted messages: on + let prefAttachPgpKey = false; // attach key to signed messages: off + let prefProtectSubject = false; // encrypt subject of encrypted message: off + + let expectSendEncrypted = false; + let expectSendSigned = true; + let expectAttachMyPublicPGPKey = false; + let expectEncryptSubject = false; + let testToggle = "encrypt"; + let expectSendEncrypted2AfterToggle = true; + let expectSendSigned2AfterToggle = true; + let expectAttachMyPublicPGPKey2AfterToggle = false; + let expectEncryptSubject2AfterToggle = false; + let switchIdentity = true; + let expectSendEncrypted3GoneToPlainIdentity = true; + let expectSendSigned3GoneToPlainIdentity = false; + let expectAttachMyPublicPGPKey3GoneToPlainIdentity = false; + let expectEncryptSubject3GoneToPlainIdentity = true; + let expectSendEncrypted4GoneToOrigIdentity = true; + let expectSendSigned4GoneToOrigIdentity = true; + let expectAttachMyPublicPGPKey4GoneToOrigIdentity = false; + let expectEncryptSubject4GoneToOrigIdentity = false; + + await testComposeFlags( + prefEncryptionPolicy, + prefSignMail, + prefAttachPgpKey, + prefProtectSubject, + expectSendEncrypted, + expectSendSigned, + expectAttachMyPublicPGPKey, + expectEncryptSubject, + testToggle, + expectSendEncrypted2AfterToggle, + expectSendSigned2AfterToggle, + expectAttachMyPublicPGPKey2AfterToggle, + expectEncryptSubject2AfterToggle, + switchIdentity, + expectSendEncrypted3GoneToPlainIdentity, + expectSendSigned3GoneToPlainIdentity, + expectAttachMyPublicPGPKey3GoneToPlainIdentity, + expectEncryptSubject3GoneToPlainIdentity, + expectSendEncrypted4GoneToOrigIdentity, + expectSendSigned4GoneToOrigIdentity, + expectAttachMyPublicPGPKey4GoneToOrigIdentity, + expectEncryptSubject4GoneToOrigIdentity + ); +}); + +registerCleanupFunction(function tearDown() { + MailServices.accounts.removeIncomingServer(bobAcct.incomingServer, true); + MailServices.accounts.removeAccount(bobAcct, true); +}); diff --git a/comm/mail/test/browser/openpgp/composition/browser_editDraftTemplate.js b/comm/mail/test/browser/openpgp/composition/browser_editDraftTemplate.js new file mode 100644 index 0000000000..e1e49927a6 --- /dev/null +++ b/comm/mail/test/browser/openpgp/composition/browser_editDraftTemplate.js @@ -0,0 +1,221 @@ +/* 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/. */ + +"use strict"; + +/** + * Tests that drafts and templates get the appropriate security properties + * when opened. + */ + +var { open_compose_new_mail, setup_msg_contents } = ChromeUtils.import( + "resource://testing-common/mozmill/ComposeHelpers.jsm" +); + +var { + be_in_folder, + get_about_3pane, + get_special_folder, + mc, + right_click_on_row, + select_click_row, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +var { OpenPGPTestUtils } = ChromeUtils.import( + "resource://testing-common/mozmill/OpenPGPTestUtils.jsm" +); + +var { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +let aliceAcct; +let aliceIdentity; +let draftsFolder; +let templatesFolder; + +/** + * Helper function to wait for a compose window to get opened. + * + * @returns The opened window. + */ +async function waitForComposeWindow() { + return BrowserTestUtils.domWindowOpened(null, async win => { + await BrowserTestUtils.waitForEvent(win, "load"); + return ( + win.document.documentURI === + "chrome://messenger/content/messengercompose/messengercompose.xhtml" + ); + }); +} + +function clearFolder(folder) { + return new Promise(resolve => { + let msgs = [...folder.msgDatabase.enumerateMessages()]; + + folder.deleteMessages( + msgs, + null, + true, + false, + { OnStopCopy: resolve }, + false + ); + }); +} + +add_setup(async function () { + aliceAcct = MailServices.accounts.createAccount(); + aliceAcct.incomingServer = MailServices.accounts.createIncomingServer( + "alice", + "openpgp.example", + "pop3" + ); + aliceIdentity = MailServices.accounts.createIdentity(); + aliceIdentity.email = "alice@openpgp.example"; + aliceAcct.addIdentity(aliceIdentity); + + let [id] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/alice@openpgp.example-0xf231550c4f47e38e-secret.asc" + ) + ) + ); + + Assert.ok(id, "private key imported"); + + aliceIdentity.setUnicharAttribute("openpgp_key_id", id.split("0x").join("")); + + draftsFolder = await get_special_folder( + Ci.nsMsgFolderFlags.Drafts, + true, + aliceAcct.incomingServer.localFoldersServer + ); + + templatesFolder = await get_special_folder( + Ci.nsMsgFolderFlags.Templates, + true, + aliceAcct.incomingServer.localFoldersServer + ); +}); + +/** + * Create draft, make sure the sec properties are as they should after + * opening. + */ +add_task(async function testDraftSec() { + await be_in_folder(draftsFolder); + await doTestSecState(true, false); // draft, not secure + await doTestSecState(true, true); // draft, secure +}); + +/** + * Create template, make sure the sec properties are as they should after + * opening. + */ +add_task(async function testTemplSec() { + await be_in_folder(templatesFolder); + await doTestSecState(false, false); // template, not secure + await doTestSecState(false, true); // template, secure +}); + +/** + * Drafts/templates are stored encrypted before sent. Test that when composing + * and the reopening, the correct encryption states get set. + */ +async function doTestSecState(isDraft, secure) { + // Make sure to compose from alice. + let inbox = aliceAcct.incomingServer.rootFolder.getFolderWithFlags( + Ci.nsMsgFolderFlags.Inbox + ); + await be_in_folder(inbox); + + let cwc = open_compose_new_mail(); + let type = isDraft ? "draft" : "template"; + let theFolder = isDraft ? draftsFolder : templatesFolder; + let subject = `test ${type}; 🤐; secure=${secure}`; + setup_msg_contents( + cwc, + "test@example.invalid", + subject, + `This is a ${type}; secure=${secure}` + ); + info(`Testing ${type}; secure=${secure}`); + + if (secure) { + // Tick "Require encryption". + // Encryption and signing should get turned on. + await OpenPGPTestUtils.toggleMessageEncryption(cwc.window); + } + + if (isDraft) { + cwc.window.SaveAsDraft(); + } else { + cwc.window.SaveAsTemplate(); + } + + await TestUtils.waitForCondition( + () => !cwc.window.gSaveOperationInProgress && !cwc.window.gWindowLock, + "timeout waiting for saving to finish." + ); + + info(`Saved as ${type} with secure=${secure}`); + cwc.window.close(); + + await be_in_folder(theFolder); + select_click_row(0); + + info(`Will open the ${type}`); + let draftWindowPromise = waitForComposeWindow(); + select_click_row(0); + await right_click_on_row(0); + + let about3Pane = get_about_3pane(); + let mailContext = about3Pane.document.getElementById("mailContext"); + if (isDraft) { + mailContext.activateItem( + about3Pane.document.getElementById("mailContext-editDraftMsg") + ); + } else { + mailContext.activateItem( + about3Pane.document.getElementById("mailContext-newMsgFromTemplate") + ); + } + + let draftWindow = await draftWindowPromise; + + Assert.equal( + draftWindow.document.getElementById("msgSubject").value, + subject, + "subject should be decrypted" + ); + + info(`Checking security props in the UI...`); + + if (!secure) { + // Wait some to make sure it won't (soon) be showing. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(resolve => setTimeout(resolve, 100)); + Assert.ok( + !draftWindow.document.getElementById("button-encryption").checked, + "should not use encryption" + ); + } else { + await TestUtils.waitForCondition( + () => draftWindow.document.getElementById("button-encryption").checked, + "waited for encryption to get turned on" + ); + } + + draftWindow.close(); + clearFolder(theFolder); +} + +registerCleanupFunction(async function () { + MailServices.accounts.removeAccount(aliceAcct, true); + await OpenPGPTestUtils.removeKeyById("0xf231550c4f47e38e", true); +}); diff --git a/comm/mail/test/browser/openpgp/composition/browser_expiredKey.js b/comm/mail/test/browser/openpgp/composition/browser_expiredKey.js new file mode 100644 index 0000000000..bf5c7e195d --- /dev/null +++ b/comm/mail/test/browser/openpgp/composition/browser_expiredKey.js @@ -0,0 +1,137 @@ +/* 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/. */ + +"use strict"; + +/** + * Tests for composition when a key is expired. + */ + +const { close_compose_window, open_compose_new_mail } = ChromeUtils.import( + "resource://testing-common/mozmill/ComposeHelpers.jsm" +); + +const { get_notification, wait_for_notification_to_show } = ChromeUtils.import( + "resource://testing-common/mozmill/NotificationBoxHelpers.jsm" +); + +const { OpenPGPTestUtils } = ChromeUtils.import( + "resource://testing-common/mozmill/OpenPGPTestUtils.jsm" +); + +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +var gAccount; +var gIdentity; +var gExpiredKeyId; +var gNotExpiredKeyId; + +add_setup(async () => { + gAccount = MailServices.accounts.createAccount(); + gAccount.incomingServer = MailServices.accounts.createIncomingServer( + "eddie", + "openpgp.example", + "imap" + ); + + gIdentity = MailServices.accounts.createIdentity(); + gIdentity.email = "eddie@openpgp.example"; + gAccount.addIdentity(gIdentity); + MailServices.accounts.defaultAccount = gAccount; + MailServices.accounts.defaultAccount.defaultIdentity = gIdentity; + + [gExpiredKeyId] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/eddie@openpgp.example-0x15e9357d2c2395c0-secret.asc" + ) + ) + ); + [gNotExpiredKeyId] = await OpenPGPTestUtils.importPrivateKey( + window, + new FileUtils.File( + getTestFilePath( + "../data/keys/alice@openpgp.example-0xf231550c4f47e38e-secret.asc" + ) + ) + ); + // FIXME: ^^^ should use a non-expiring key matching EDDIE! + + registerCleanupFunction(async () => { + await OpenPGPTestUtils.removeKeyById(gExpiredKeyId, true); + await OpenPGPTestUtils.removeKeyById(gNotExpiredKeyId, true); + MailServices.accounts.removeIncomingServer(gAccount.incomingServer, true); + MailServices.accounts.removeAccount(gAccount, true); + }); +}); + +add_task(async function testExpiredKeyShowsNotificationBar() { + Services.wm + .getMostRecentWindow("mail:3pane") + .document.getElementById("tabmail") + .currentAbout3Pane.displayFolder(gAccount.incomingServer.rootFolder); + info(`Using key ${gExpiredKeyId}`); + gIdentity.setUnicharAttribute( + "openpgp_key_id", + gExpiredKeyId.replace(/^0x/, "") + ); + let cwc = open_compose_new_mail(); + + wait_for_notification_to_show( + cwc.window, + "compose-notification-bottom", + "openpgpSenderKeyExpired" + ); + let notification = get_notification( + cwc.window, + "compose-notification-bottom", + "openpgpSenderKeyExpired" + ); + + Assert.ok(notification !== null, "notification should be visible"); + Assert.equal( + notification.messageText.textContent, + "Your current configuration uses the key 0x15E9357D2C2395C0, which has expired.", + "correct notification message should be displayed" + ); + + const buttons = notification._buttons; + Assert.equal( + buttons[0]["l10n-id"], + "settings-context-open-account-settings-item2", + "button0 should be the button to open account settings" + ); + cwc.window.close(); +}); + +add_task(async function testKeyWithoutExpiryDoesNotShowNotification() { + Services.wm + .getMostRecentWindow("mail:3pane") + .document.getElementById("tabmail") + .currentAbout3Pane.displayFolder(gAccount.incomingServer.rootFolder); + info(`Using key ${gNotExpiredKeyId}`); + gIdentity.setUnicharAttribute( + "openpgp_key_id", + gNotExpiredKeyId.replace(/^0x/, "") + ); + let cwc = open_compose_new_mail(); + + // Give it some time to potentially start showing. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(resolve => setTimeout(resolve, 200)); + let notification = get_notification( + cwc.window, + "compose-notification-bottom", + "openpgpSenderKeyExpired" + ); + + Assert.ok( + notification === null, + "the expiry warning should not be visible if the key is not expired" + ); + cwc.window.close(); +}); diff --git a/comm/mail/test/browser/openpgp/composition/head.js b/comm/mail/test/browser/openpgp/composition/head.js new file mode 100644 index 0000000000..b0b9b54d76 --- /dev/null +++ b/comm/mail/test/browser/openpgp/composition/head.js @@ -0,0 +1,18 @@ +/* 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/. */ + +"use strict"; + +/** + * Uses the "cmd_sendLater" to store the message in the passed compose window + * in the outbox. + */ +async function sendMessage(win) { + let closePromise = BrowserTestUtils.domWindowClosed(win); + win.goDoCommand("cmd_sendLater"); + await closePromise; + + // Give encryption/signing time to finish. + return new Promise(resolve => setTimeout(resolve)); +} |