Bug 1677062 - Expose gComposeType as type in ComposeDetails. r=darktrojan
authorJohn Bieling <john@thunderbird.net>
Mon, 22 Feb 2021 08:48:08 +0100
changeset 41421 947d10fcdca77a47c861981f40ff3aaa5786d1a0
parent 41420 1a40c3dd9d779c29452856140d5fc4ccc0c5daa1
child 41422 4e67bbcddb96c7b9c5a12da97023795157cec171
push id3019
push usertbbld-merge
push dateMon, 22 Mar 2021 16:17:19 +0000
treeherdercomm-beta@17ae5ec643b4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdarktrojan
bugs1677062
Bug 1677062 - Expose gComposeType as type in ComposeDetails. r=darktrojan
mail/components/extensions/parent/ext-compose.js
mail/components/extensions/schemas/compose.json
mail/components/extensions/test/browser/browser_ext_compose_details.js
--- a/mail/components/extensions/parent/ext-compose.js
+++ b/mail/components/extensions/parent/ext-compose.js
@@ -258,20 +258,51 @@ async function getComposeDetails(compose
       once: true,
     })
   );
   if (!composeWindow.composeEditorReady) {
     await composeEditorReady;
   }
   let editor = composeWindow.GetCurrentEditor();
 
+  let type;
+  // check all known nsIMsgComposeParams
+  switch (composeWindow.gComposeType) {
+    case Ci.nsIMsgCompType.Draft:
+      type = "draft";
+      break;
+    case Ci.nsIMsgCompType.New:
+    case Ci.nsIMsgCompType.Template:
+    case Ci.nsIMsgCompType.MailToUrl:
+    case Ci.nsIMsgCompType.EditAsNew:
+    case Ci.nsIMsgCompType.EditTemplate:
+    case Ci.nsIMsgCompType.Redirect:
+    case Ci.nsIMsgCompType.NewsPost:
+      type = "new";
+      break;
+    case Ci.nsIMsgCompType.Reply:
+    case Ci.nsIMsgCompType.ReplyAll:
+    case Ci.nsIMsgCompType.ReplyToSender:
+    case Ci.nsIMsgCompType.ReplyToGroup:
+    case Ci.nsIMsgCompType.ReplyToSenderAndGroup:
+    case Ci.nsIMsgCompType.ReplyWithTemplate:
+    case Ci.nsIMsgCompType.ReplyToList:
+      type = "reply";
+      break;
+    case Ci.nsIMsgCompType.ForwardAsAttachment:
+    case Ci.nsIMsgCompType.ForwardInline:
+      type = "forward";
+      break;
+  }
+
   let details = {
     to: composeFields.splitRecipients(composeFields.to, false),
     cc: composeFields.splitRecipients(composeFields.cc, false),
     bcc: composeFields.splitRecipients(composeFields.bcc, false),
+    type,
     replyTo: composeFields.splitRecipients(composeFields.replyTo, false),
     followupTo: composeFields.splitRecipients(composeFields.followupTo, false),
     newsgroups: composeFields.newsgroups
       ? composeFields.newsgroups.split(",")
       : [],
     subject: composeFields.subject,
     isPlainText: !composeWindow.IsHTMLEditor(),
     body: editor.outputToString("text/html", 0),
--- a/mail/components/extensions/schemas/compose.json
+++ b/mail/components/extensions/schemas/compose.json
@@ -104,16 +104,27 @@
               }
             ],
             "optional": true
           },
           "subject": {
             "type": "string",
             "optional": true
           },
+          "type": {
+            "type": "string",
+            "description": "Read-only. The type of the message being composed, depending on how the compose window was opened by the user.",
+            "enum": [
+              "draft",
+              "new",
+              "reply",
+              "forward"
+            ],
+            "optional": true
+          },
           "body": {
             "type": "string",
             "optional": true
           },
           "plainTextBody": {
             "type": "string",
             "optional": true
           },
--- a/mail/components/extensions/test/browser/browser_ext_compose_details.js
+++ b/mail/components/extensions/test/browser/browser_ext_compose_details.js
@@ -1,15 +1,25 @@
 /* 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/. */
 
 let account = createAccount();
 let defaultIdentity = addIdentity(account);
 let nonDefaultIdentity = addIdentity(account);
+let gRootFolder = account.incomingServer.rootFolder;
+
+gRootFolder.createSubfolder("test", null);
+let gTestFolder = gRootFolder.getChildNamed("test");
+createMessages(gTestFolder, 4);
+
+gRootFolder.createSubfolder("drafts", null);
+let gDraftsFolder = gRootFolder.getChildNamed("drafts");
+gDraftsFolder.flags = Ci.nsMsgFolderFlags.Drafts;
+createMessages(gDraftsFolder, 2);
 
 add_task(async function testHeaders() {
   let files = {
     "background.js": async () => {
       async function checkWindow(expected) {
         let state = await browser.compose.getComposeDetails(createdTab.id);
         for (let field of [
           "to",
@@ -598,8 +608,128 @@ add_task(async function testBody() {
   closePromises = [
     // If the window is not marked as dirty, this Promise will never resolve.
     BrowserTestUtils.promiseAlertDialog("extra1"),
     BrowserTestUtils.domWindowClosed(plainTextWindow),
   ];
   plainTextWindow.DoCommandClose();
   await Promise.all(closePromises);
 });
+
+add_task(async function testType() {
+  let files = {
+    "background.js": async () => {
+      let accounts = await browser.accounts.list();
+      browser.test.assertEq(1, accounts.length, "number of accounts");
+
+      let testFolder = accounts[0].folders.find(f => f.name == "test");
+      let messages = (await browser.messages.list(testFolder)).messages;
+      browser.test.assertEq(4, messages.length, "number of messages");
+
+      let draftFolder = accounts[0].folders.find(f => f.name == "drafts");
+      let drafts = (await browser.messages.list(draftFolder)).messages;
+      browser.test.assertEq(2, drafts.length, "number of drafts");
+
+      async function checkComposer(tab, expected) {
+        browser.test.assertEq("object", typeof tab, "type of tab");
+        browser.test.assertEq("number", typeof tab.id, "type of tab ID");
+        browser.test.assertEq(
+          "number",
+          typeof tab.windowId,
+          "type of window ID"
+        );
+
+        let details = await browser.compose.getComposeDetails(tab.id);
+        browser.test.assertEq(expected.type, details.type, "type of composer");
+        await browser.windows.remove(tab.windowId);
+      }
+
+      let tests = [
+        {
+          funcName: "beginNew",
+          args: [],
+          expected: { type: "new" },
+        },
+        {
+          funcName: "beginReply",
+          args: [messages[0].id],
+          expected: { type: "reply" },
+        },
+        {
+          funcName: "beginReply",
+          args: [messages[1].id, "replyToAll"],
+          expected: { type: "reply" },
+        },
+        {
+          funcName: "beginReply",
+          args: [messages[2].id, "replyToList"],
+          expected: { type: "reply" },
+        },
+        {
+          funcName: "beginReply",
+          args: [messages[3].id, "replyToSender"],
+          expected: { type: "reply" },
+        },
+        {
+          funcName: "beginForward",
+          args: [messages[0].id],
+          expected: { type: "forward" },
+        },
+        {
+          funcName: "beginForward",
+          args: [messages[1].id, "forwardAsAttachment"],
+          expected: { type: "forward" },
+        },
+        // Uses a different code path.
+        {
+          funcName: "beginForward",
+          args: [messages[2].id, "forwardInline"],
+          expected: { type: "forward" },
+        },
+        {
+          funcName: "beginNew",
+          args: [messages[3].id],
+          expected: { type: "new" },
+        },
+      ];
+      for (let test of tests) {
+        browser.test.log(test.funcName);
+        let tab = await browser.compose[test.funcName](...test.args);
+        await checkComposer(tab, test.expected);
+      }
+
+      browser.tabs.onCreated.addListener(async tab => {
+        let window = await browser.windows.get(tab.windowId);
+        if (window.type == "messageCompose") {
+          await checkComposer(tab, { type: "draft" });
+          browser.test.notifyPass("Finish");
+        }
+      });
+      browser.test.sendMessage("openDrafts");
+    },
+    "utils.js": await getUtilsJS(),
+  };
+  let extension = ExtensionTestUtils.loadExtension({
+    files,
+    manifest: {
+      background: { scripts: ["utils.js", "background.js"] },
+      permissions: ["compose", "accountsRead", "messagesRead"],
+    },
+  });
+
+  await extension.startup();
+
+  // The first part of the test is done in the background script using the
+  // compose API to open compose windows. For the second part we need to open
+  // a draft, which is not possible with the compose API.
+  await extension.awaitMessage("openDrafts");
+  // Select a draft and click on the Edit button.
+  window.gFolderTreeView.selectFolder(gDraftsFolder);
+  window.gFolderDisplay.selectViewIndex(0);
+  await BrowserTestUtils.browserLoaded(window.getMessagePaneBrowser());
+  let button = window.document.querySelector(
+    `notification[value="draftMsgContent"] button`
+  );
+  EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 });
+
+  await extension.awaitFinish("Finish");
+  await extension.unload();
+});