Bug 1588391 - In WebExtensions folder lookup, don't encode path components for IMAP servers; r=mkmelin
authorGeoff Lankow <geoff@darktrojan.net>
Tue, 15 Oct 2019 11:55:27 +1300
changeset 37163 7fc4bc60717ae9956315068405022e2209501967
parent 37162 abd059b8c2084f70365fdbaee59c2ccdfac24be6
child 37164 14258a1ca363e616e973e31b5cadaa7bd995cd5f
push id395
push userclokep@gmail.com
push dateMon, 02 Dec 2019 19:38:57 +0000
reviewersmkmelin
bugs1588391
Bug 1588391 - In WebExtensions folder lookup, don't encode path components for IMAP servers; r=mkmelin
mail/components/extensions/parent/ext-mail.js
mail/components/extensions/test/xpcshell/test_ext_accounts.js
--- a/mail/components/extensions/parent/ext-mail.js
+++ b/mail/components/extensions/parent/ext-mail.js
@@ -1245,21 +1245,26 @@ function folderURIToPath(uri) {
 }
 
 /**
  * Convert a human-friendly path to a folder URI. This function does not assume that the
  * folder referenced exists.
  * @return {String}
  */
 function folderPathToURI(accountId, path) {
-  let rootURI = MailServices.accounts.getAccount(accountId).incomingServer
-    .rootFolder.URI;
+  let server = MailServices.accounts.getAccount(accountId).incomingServer;
+  let rootURI = server.rootFolder.URI;
   if (path == "/") {
     return rootURI;
   }
+  // The .URI property of an IMAP folder doesn't have %-encoded characters.
+  // If encoded here, the folder lookup service won't find the folder.
+  if (server.type == "imap") {
+    return rootURI + path;
+  }
   return (
     rootURI +
     path
       .split("/")
       .map(encodeURIComponent)
       .join("/")
   );
 }
--- a/mail/components/extensions/test/xpcshell/test_ext_accounts.js
+++ b/mail/components/extensions/test/xpcshell/test_ext_accounts.js
@@ -4,16 +4,24 @@
 
 "use strict";
 
 var { ExtensionTestUtils } = ChromeUtils.import(
   "resource://testing-common/ExtensionXPCShellUtils.jsm"
 );
 ExtensionTestUtils.init(this);
 
+var imapd = ChromeUtils.import("resource://testing-common/mailnews/imapd.js");
+var { nsMailServer } = ChromeUtils.import(
+  "resource://testing-common/mailnews/maild.js"
+);
+var { PromiseTestUtils } = ChromeUtils.import(
+  "resource://testing-common/mailnews/PromiseTestUtils.jsm"
+);
+
 add_task(async function test_accounts() {
   let extension = ExtensionTestUtils.loadExtension({
     async background() {
       function awaitMessage(messageToSend) {
         return new Promise(resolve => {
           browser.test.onMessage.addListener(function listener(...args) {
             browser.test.onMessage.removeListener(listener);
             resolve(args);
@@ -84,17 +92,17 @@ add_task(async function test_accounts() 
 
       let [account2Id] = await awaitMessage("create account 2");
       let result2 = await browser.accounts.list();
       browser.test.assertEq(2, result2.length);
       assertDeepEqual(result1[0], result2[0]);
       assertDeepEqual(
         {
           id: account2Id,
-          name: "Mail for username@hostname",
+          name: "Mail for xpcshell@localhost",
           type: "imap",
           folders: [
             {
               accountId: account2Id,
               name: "Inbox",
               path: "/INBOX",
               type: "inbox",
             },
@@ -136,41 +144,102 @@ add_task(async function test_accounts() 
             name: "Outbox",
             path: "/Unsent Messages",
             type: "outbox",
           },
         ],
         result5.folders
       );
 
+      // Check we can access the folders through folderPathToURI.
+      for (let folder of result5.folders) {
+        await browser.messages.list(folder);
+      }
+
+      let result6 = await browser.accounts.get(account2Id);
+      assertDeepEqual(
+        [
+          {
+            accountId: account2Id,
+            name: "Inbox",
+            path: "/INBOX",
+            type: "inbox",
+          },
+          {
+            accountId: account2Id,
+            name: "foo bar",
+            path: "/INBOX/foo bar",
+          },
+          {
+            accountId: account2Id,
+            name: "Ϟ",
+            path: "/INBOX/&A94-",
+          },
+          {
+            // The trash folder magically appears at this point.
+            // It wasn't here before.
+            accountId: "account2",
+            name: "Trash",
+            path: "/Trash",
+            type: "trash",
+          },
+        ],
+        result6.folders
+      );
+
+      // Check we can access the folders through folderPathToURI.
+      for (let folder of result6.folders) {
+        await browser.messages.list(folder);
+      }
+
       browser.test.notifyPass("finished");
     },
     manifest: {
-      permissions: ["accountsRead"],
+      permissions: ["accountsRead", "messagesRead"],
     },
   });
 
+  let daemon = new imapd.imapDaemon();
+  let server = new nsMailServer(function createHandler(d) {
+    return new imapd.IMAP_RFC3501_handler(d);
+  }, daemon);
+  server.start();
+
   let account1 = createAccount();
 
   await extension.startup();
   extension.sendMessage(account1.key);
 
   await extension.awaitMessage("create account 2");
   let account2 = MailServices.accounts.createAccount();
-  account2.incomingServer = MailServices.accounts.createIncomingServer(
-    "username",
-    "hostname",
+  addIdentity(account2);
+  let iServer = MailServices.accounts.createIncomingServer(
+    "user",
+    "localhost",
     "imap"
   );
+  iServer.port = server.port;
+  iServer.username = "user";
+  iServer.password = "password";
+  account2.incomingServer = iServer;
+
   extension.sendMessage(account2.key);
 
   await extension.awaitMessage("create folders");
   let inbox1 = [...account1.incomingServer.rootFolder.subFolders][0];
   inbox1.createSubfolder("foo bar", null); // Test our code can handle spaces.
   inbox1.createSubfolder("Ϟ", null); // Test our code can handle unicode.
+
+  let inbox2 = [...account2.incomingServer.rootFolder.subFolders][0];
+  inbox2.QueryInterface(Ci.nsIMsgImapMailFolder).hierarchyDelimiter = "/";
+  inbox2.createSubfolder("foo bar", null); // Test our code can handle spaces.
+  await PromiseTestUtils.promiseFolderAdded("foo bar");
+  inbox2.createSubfolder("Ϟ", null); // Test our code can handle unicode.
+  await PromiseTestUtils.promiseFolderAdded("Ϟ");
+
   extension.sendMessage();
 
   await extension.awaitFinish("finished");
   await extension.unload();
 
   cleanUpAccount(account1);
   cleanUpAccount(account2);
 });