Bug 1720042 - Support importing csv/tsv file in AddrBookFileImporter.jsm. r=benc

Differential Revision: https://phabricator.services.mozilla.com/D140016
This commit is contained in:
Ping Chen 2022-03-02 05:41:06 +00:00
Родитель f4d8992467
Коммит 6a82a3cbd8
6 изменённых файлов: 99 добавлений и 3 удалений

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

@ -3,6 +3,7 @@
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
const EXPORTED_SYMBOLS = [
"exportAttributes",
"AddrBookUtils",
"compareAddressBooks",
"newUID",

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

@ -501,6 +501,7 @@ class AddrBookImporterController extends ImporterController {
async _showDirectories(sourceFile) {
this._sourceFile = sourceFile;
let elList = document.getElementById("directoryList");
elList.innerHTML = "";
this._directories = MailServices.ab.directories.filter(
dir => dir.dirType == Ci.nsIAbManager.JS_DIRECTORY_TYPE
);

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

@ -4,7 +4,24 @@
const EXPORTED_SYMBOLS = ["AddrBookFileImporter"];
var { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyModuleGetters(this, {
Services: "resource://gre/modules/Services.jsm",
setTimeout: "resource://gre/modules/Timer.jsm",
exportAttributes: "resource:///modules/AddrBookUtils.jsm",
});
XPCOMUtils.defineLazyGetter(this, "d3", () => {
let d3Scope = Cu.Sandbox(null);
Services.scriptloader.loadSubScript(
"chrome://global/content/third_party/d3/d3.js",
d3Scope
);
return Cu.waiveXrays(d3Scope.d3);
});
/**
* A module to import address book files.
@ -44,6 +61,9 @@ class AddrBookFileImporter {
this._targetDirectory = targetDirectory;
switch (this._type) {
case "csv":
await this._importCsvFile();
break;
case "ldif":
await this._importLdifFile();
break;
@ -61,6 +81,65 @@ class AddrBookFileImporter {
}
}
/**
* Import the .csv/.tsv source file into the target directory.
*/
async _importCsvFile() {
let content = await IOUtils.readUTF8(this._sourceFile.path);
let csvRows = d3.csv.parseRows(content);
let tsvRows = d3.tsv.parseRows(content);
// If we have more CSV columns, then it's a CSV file, otherwise a TSV file.
let rows = csvRows[0].length > tsvRows[0].length ? csvRows : tsvRows;
let bundle = Services.strings.createBundle(
"chrome://messenger/locale/importMsgs.properties"
);
let supportedFieldNames = [];
let supportedProperties = [];
// Collect field names in an exported CSV file, and their corresponding
// nsIAbCard property names.
for (let [property, stringId] of exportAttributes) {
if (stringId) {
supportedProperties.push(property);
supportedFieldNames.push(
bundle.GetStringFromID(stringId).toLowerCase()
);
}
}
let properties = [];
// Get the nsIAbCard properties corresponding to the user supplied file.
for (let field of rows[0]) {
let index = supportedFieldNames.indexOf(field.toLowerCase());
properties.push(supportedProperties[index]);
}
let totalLines = rows.length - 1;
let currentLine = 0;
for (let row of rows.slice(1)) {
currentLine++;
let card = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance(
Ci.nsIAbCard
);
for (let i = 0; i < row.length; i++) {
let property = properties[i];
if (!property) {
continue;
}
// Set the field value to the property.
card.setProperty(property, row[i]);
}
this._targetDirectory.addCard(card);
if (currentLine % 10 == 0) {
this.onProgress(currentLine, totalLines);
// Give UI a chance to update the progress bar.
await new Promise(resolve => setTimeout(resolve));
}
}
this.onProgress(totalLines, totalLines);
}
/**
* Import the .ldif source file into the target directory.
*/

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

@ -71,7 +71,7 @@
[
{
"DisplayName" : "Acer America",
"Work Phone" : "(800) 000-0000",
"WorkPhone" : "(800) 000-0000",
"Organization" : "Acer America"
}
],

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

@ -228,6 +228,10 @@ AbImportHelper.prototype = {
var fieldMap = importService.CreateNewFieldMap();
fieldMap.DefaultFieldMap(fieldMap.numMozFields);
this.mInterface
.GetData("addressInterface")
.QueryInterface(Ci.nsIImportAddressBooks)
.InitFieldMap(fieldMap);
fieldMap.skipFirstRecord = aSkipFirstRecord;
return fieldMap;

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

@ -34,7 +34,7 @@ async function test_importAbFile(type, testFile, refDataKey) {
for (let i = 0; i < refData.length; i++) {
let card = targetDir.childCards[i];
for (let [key, value] of Object.entries(refData[i])) {
if (["LastModifiedDate"].includes(key)) {
if (["LastModifiedDate", "Organization"].includes(key)) {
continue;
}
equal(value, card.getProperty(key, ""), `${key} should be correct`);
@ -42,6 +42,17 @@ async function test_importAbFile(type, testFile, refDataKey) {
}
}
/** Test importing .csv file works. */
add_task(async function test_importCsvFile() {
await test_importAbFile(
"csv",
"resources/basic_csv_addressbook.csv",
"csv_import"
);
await test_importAbFile("csv", "resources/quote.csv", "quote_csv");
});
/** Test importing .vcf file works. */
add_task(async function test_importVCardFile() {
return test_importAbFile(