Bug 1531591 - WebExtensions API for creating/modifying/deleting folders; r=mkmelin

This commit is contained in:
Geoff Lankow 2019-04-10 12:29:57 +12:00
Родитель 5bdb6cc9a3
Коммит 08bb5a6f90
5 изменённых файлов: 211 добавлений и 5 удалений

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

@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
ChromeUtils.defineModuleGetter(this, "MailServices", "resource:///modules/MailServices.jsm");
var { fixIterator } = ChromeUtils.import("resource:///modules/iteratorUtils.jsm");
ChromeUtils.defineModuleGetter(this, "fixIterator", "resource:///modules/iteratorUtils.jsm");
ChromeUtils.defineModuleGetter(this, "toXPCOMArray", "resource:///modules/iteratorUtils.jsm");
function convertAccount(account) {
account = account.QueryInterface(Ci.nsIMsgAccount);
@ -50,6 +51,84 @@ this.accounts = class extends ExtensionAPI {
}
return null;
},
async createSubfolder({ accountId, path: parentPath }, childName) {
let uri = folderPathToURI(accountId, parentPath);
let parentFolder = MailServices.folderLookup.getFolderForURL(uri);
if (!parentFolder) {
throw new ExtensionError(`Folder not found: ${parentPath}`);
}
let childFolder = await new Promise((resolve) => {
MailServices.mfn.addListener({
folderAdded(childFolder) {
if (childFolder.parent.URI != uri) {
return;
}
MailServices.mfn.removeListener(this);
resolve(childFolder);
},
}, MailServices.mfn.folderAdded);
parentFolder.createSubfolder(childName, null);
});
return convertFolder(childFolder);
},
async renameFolder({ accountId, path }, newName) {
let uri = folderPathToURI(accountId, path);
let folder = MailServices.folderLookup.getFolderForURL(uri);
if (!folder) {
throw new ExtensionError(`Folder not found: ${path}`);
}
let newFolder = await new Promise((resolve) => {
MailServices.mfn.addListener({
folderRenamed(oldFolder, newFolder) {
if (oldFolder.URI != uri) {
return;
}
MailServices.mfn.removeListener(this);
resolve(newFolder);
},
}, MailServices.mfn.folderRenamed);
folder.rename(newName, null);
});
return convertFolder(newFolder);
},
async deleteFolder({ accountId, path }) {
let uri = folderPathToURI(accountId, path);
let folder = MailServices.folderLookup.getFolderForURL(uri);
if (!folder) {
throw new ExtensionError(`Folder not found: ${path}`);
}
await new Promise((resolve) => {
MailServices.mfn.addListener({
folderDeleted(oldFolder) {
if (oldFolder.URI != uri) {
return;
}
MailServices.mfn.removeListener(this);
resolve();
},
folderMoveCopyCompleted(move, srcFolder, destFolder) {
if (srcFolder.URI != uri) {
return;
}
MailServices.mfn.removeListener(this);
resolve();
},
}, MailServices.mfn.folderDeleted | MailServices.mfn.folderMoveCopyCompleted);
folder.parent.deleteSubFolders(toXPCOMArray([folder], Ci.nsIMutableArray), null);
});
},
},
};
}

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

@ -8,6 +8,7 @@
{
"type": "string",
"enum": [
"accountsFolders",
"accountsRead"
]
}
@ -67,6 +68,57 @@
"type": "string"
}
]
},
{
"name": "createSubfolder",
"type": "function",
"description": "Creates a new subfolder of <code>parentFolder</code>.",
"permissions": [
"accountsFolders"
],
"async": true,
"parameters": [
{
"name": "parentFolder",
"$ref": "accounts.MailFolder"
}, {
"name": "childName",
"type": "string"
}
]
},
{
"name": "renameFolder",
"type": "function",
"description": "Renames a folder.",
"permissions": [
"accountsFolders"
],
"async": true,
"parameters": [
{
"name": "folder",
"$ref": "accounts.MailFolder"
}, {
"name": "newName",
"type": "string"
}
]
},
{
"name": "deleteFolder",
"type": "function",
"description": "Deletes a folder.",
"permissions": [
"accountsFolders"
],
"async": true,
"parameters": [
{
"name": "folder",
"$ref": "accounts.MailFolder"
}
]
}
]
}

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

@ -15,10 +15,6 @@ Services.prefs.deleteBranch("ldap_2.servers.oe.");
Services.prefs.deleteBranch("ldap_2.servers.osx.");
function createAccount() {
registerCleanupFunction(() => {
[...MailServices.accounts.accounts.enumerate()].forEach(cleanUpAccount);
});
MailServices.accounts.createLocalMailAccount();
let account = MailServices.accounts.accounts.enumerate().getNext().QueryInterface(Ci.nsIMsgAccount);
account.incomingServer = MailServices.accounts.localFoldersServer;
@ -33,6 +29,10 @@ function cleanUpAccount(account) {
MailServices.accounts.removeAccount(account, true);
}
registerCleanupFunction(() => {
[...MailServices.accounts.accounts.enumerate()].forEach(cleanUpAccount);
});
function createMessages(folder, count) {
const {
MessageGenerator,

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

@ -143,4 +143,78 @@ add_task(async function test_accounts() {
await extension.awaitFinish("finished");
await extension.unload();
cleanUpAccount(account1);
cleanUpAccount(account2);
});
add_task(async function test_folders() {
let extension = ExtensionTestUtils.loadExtension({
async background() {
let accountId = await new Promise(resolve => {
browser.test.onMessage.addListener(function listener(acctId) {
browser.test.onMessage.removeListener(listener);
resolve(acctId);
});
});
let account = await browser.accounts.get(accountId);
browser.test.assertEq(2, account.folders.length);
let folder1 = await browser.accounts.createSubfolder({ accountId, path: "/" }, "folder1");
browser.test.assertEq(accountId, folder1.accountId);
browser.test.assertEq("folder1", folder1.name);
browser.test.assertEq("/folder1", folder1.path);
account = await browser.accounts.get(accountId);
browser.test.assertEq(3, account.folders.length);
browser.test.assertEq("/folder1", account.folders[2].path);
let folder2 = await browser.accounts.createSubfolder({ accountId, path: "/folder1" }, "folder2");
browser.test.assertEq(accountId, folder2.accountId);
browser.test.assertEq("folder2", folder2.name);
browser.test.assertEq("/folder1/folder2", folder2.path);
account = await browser.accounts.get(accountId);
browser.test.assertEq(4, account.folders.length);
browser.test.assertEq("/folder1/folder2", account.folders[3].path);
let folder3 = await browser.accounts.renameFolder({ accountId, path: "/folder1/folder2" }, "folder3");
browser.test.assertEq(accountId, folder3.accountId);
browser.test.assertEq("folder3", folder3.name);
browser.test.assertEq("/folder1/folder3", folder3.path);
account = await browser.accounts.get(accountId);
browser.test.assertEq(4, account.folders.length);
browser.test.assertEq("/folder1/folder3", account.folders[3].path);
await browser.accounts.deleteFolder({ accountId, path: "/folder1/folder3" });
account = await browser.accounts.get(accountId);
browser.test.assertEq(4, account.folders.length);
browser.test.assertEq("/Trash", account.folders[0].path);
browser.test.assertEq("/Trash/folder3", account.folders[1].path);
browser.test.assertEq("/Unsent Messages", account.folders[2].path);
browser.test.assertEq("/folder1", account.folders[3].path);
await browser.accounts.deleteFolder({ accountId, path: "/Trash/folder3" });
account = await browser.accounts.get(accountId);
browser.test.assertEq(3, account.folders.length);
browser.test.assertEq("/Trash", account.folders[0].path);
browser.test.assertEq("/Unsent Messages", account.folders[1].path);
browser.test.assertEq("/folder1", account.folders[2].path);
browser.test.notifyPass("finished");
},
manifest: {
permissions: ["accountsRead", "accountsFolders"],
},
});
let account = createAccount();
await extension.startup();
extension.sendMessage(account.key);
await extension.awaitFinish("finished");
await extension.unload();
});

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

@ -148,6 +148,7 @@ webextPerms.optionalPermsAllow.accessKey=A
webextPerms.optionalPermsDeny.label=Deny
webextPerms.optionalPermsDeny.accessKey=D
webextPerms.description.accountsFolders=Create, rename, or delete your mail account folders
webextPerms.description.accountsRead=See your mail accounts and their folders
webextPerms.description.addressBooks=Read and modify your address books and contacts
webextPerms.description.bookmarks=Read and modify bookmarks