Bug 746066 - Contacts API: Add v1 and v2 fields. r=fabrice,sicking

This commit is contained in:
Gregor Wagner 2012-05-10 21:51:48 -07:00
parent 4a37a54063
commit 51e7c155b7
8 changed files with 235 additions and 82 deletions

View File

@ -36,7 +36,7 @@ IndexedDBHelper.prototype = {
/**
* Open a new database.
* User has to provide createSchema and upgradeSchema.
* User has to provide upgradeSchema.
*
* @param successCb
* Success callback to call once database is open.
@ -45,7 +45,7 @@ IndexedDBHelper.prototype = {
*/
open: function open(aSuccessCb, aFailureCb) {
let self = this;
debug("Try to open database:" + this.dbName + " " + this.dbVersion);
debug("Try to open database:" + self.dbName + " " + self.dbVersion);
let req = this.dbGlobal.mozIndexedDB.open(this.dbName, this.dbVersion);
req.onsuccess = function (event) {
debug("Opened database:" + self.dbName + " " + self.dbName);
@ -57,22 +57,14 @@ IndexedDBHelper.prototype = {
};
req.onupgradeneeded = function (aEvent) {
debug("Database needs upgrade:" + this.dbName + aEvent.oldVersion + aEvent.newVersion);
debug("Database needs upgrade:" + self.dbName + aEvent.oldVersion + aEvent.newVersion);
debug("Correct new database version:" + aEvent.newVersion == this.dbVersion);
let _db = aEvent.target.result;
switch (aEvent.oldVersion) {
case 0:
debug("New database");
self.createSchema(_db);
break;
default:
self.upgradeSchema(_db, aEvent.oldVersion, aEvent.newVersion);
break;
}
self.upgradeSchema(req.transaction, _db, aEvent.oldVersion, aEvent.newVersion);
};
req.onerror = function (aEvent) {
debug("Failed to open database:" + this.dbName);
debug("Failed to open database:" + self.dbName);
aFailureCb(aEvent.target.errorMessage);
};
req.onblocked = function (aEvent) {
@ -139,7 +131,7 @@ IndexedDBHelper.prototype = {
* @param aDBName
* DB name for the open call.
* @param aDBVersion
* Current DB version. User has to implement createSchema and upgradeSchema.
* Current DB version. User has to implement upgradeSchema.
* @param aDBStoreName
* ObjectStore that is used.
* @param aGlobal

View File

@ -28,11 +28,13 @@ XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
});
const nsIClassInfo = Ci.nsIClassInfo;
const CONTACTPROPERTIES_CID = Components.ID("{53ed7c20-ceda-11e0-9572-0800200c9a66}");
const CONTACTPROPERTIES_CID = Components.ID("{f5181640-89e8-11e1-b0c4-0800200c9a66}");
const nsIDOMContactProperties = Ci.nsIDOMContactProperties;
// ContactProperties is not directly instantiated. It is used as interface.
function ContactProperties(aProp) { debug("ContactProperties Constructor"); }
ContactProperties.prototype = {
classID : CONTACTPROPERTIES_CID,
@ -48,10 +50,11 @@ ContactProperties.prototype = {
//ContactAddress
const CONTACTADDRESS_CONTRACTID = "@mozilla.org/contactAddress;1";
const CONTACTADDRESS_CID = Components.ID("{27a568b0-cee1-11e0-9572-0800200c9a66}");
const CONTACTADDRESS_CID = Components.ID("{eba48030-89e8-11e1-b0c4-0800200c9a66}");
const nsIDOMContactAddress = Components.interfaces.nsIDOMContactAddress;
function ContactAddress(aStreetAddress, aLocality, aRegion, aPostalCode, aCountryName) {
function ContactAddress(aType, aStreetAddress, aLocality, aRegion, aPostalCode, aCountryName) {
this.type = aType || null;
this.streetAddress = aStreetAddress || null;
this.locality = aLocality || null;
this.region = aRegion || null;
@ -59,8 +62,6 @@ function ContactAddress(aStreetAddress, aLocality, aRegion, aPostalCode, aCountr
this.countryName = aCountryName || null;
};
function ContactProperties(aProp) { debug("ContactProperties Constructor"); }
ContactAddress.prototype = {
classID : CONTACTADDRESS_CID,
@ -73,6 +74,29 @@ ContactAddress.prototype = {
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactAddress])
}
//ContactTelephone
const CONTACTTELEPHONE_CONTRACTID = "@mozilla.org/contactTelephone;1";
const CONTACTTELEPHONE_CID = Components.ID("{82601b20-89e8-11e1-b0c4-0800200c9a66}");
const nsIDOMContactTelephone = Components.interfaces.nsIDOMContactTelephone;
function ContactTelephone(aType, aNumber) {
this.type = aType || null;
this.number = aNumber || null;
};
ContactTelephone.prototype = {
classID : CONTACTTELEPHONE_CID,
classInfo : XPCOMUtils.generateCI({classID: CONTACTTELEPHONE_CID,
contractID: CONTACTTELEPHONE_CONTRACTID,
classDescription: "ContactTelephone",
interfaces: [nsIDOMContactTelephone],
flags: nsIClassInfo.DOM_OBJECT}),
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactTelephone])
}
//ContactFindOptions
const CONTACTFINDOPTIONS_CONTRACTID = "@mozilla.org/contactFindOptions;1";
@ -125,19 +149,27 @@ Contact.prototype = {
if (aProp.adr) {
// Make sure adr argument is an array. Instanceof doesn't work.
aProp.adr = aProp.adr.length == undefined ? [aProp.adr] : aProp.adr;
aProp.adr = Array.isArray(aProp.adr) ? aProp.adr : [aProp.adr];
this.adr = new Array();
for (let i = 0; i < aProp.adr.length; i++)
this.adr.push(new ContactAddress(aProp.adr[i].streetAddress, aProp.adr[i].locality,
aProp.adr[i].region, aProp.adr[i].postalCode,
aProp.adr[i].countryName));
this.adr.push(new ContactAddress(aProp.adr[i].type, aProp.adr[i].streetAddress, aProp.adr[i].locality,
aProp.adr[i].region, aProp.adr[i].postalCode, aProp.adr[i].countryName));
} else {
this.adr = null;
}
this.tel = _create(aProp.tel) || null;
if (aProp.tel) {
aProp.tel = Array.isArray(aProp.tel) ? aProp.tel : [aProp.tel];
this.tel = new Array();
for (let i = 0; i < aProp.tel.length; i++)
this.tel.push(new ContactTelephone(aProp.tel[i].type, aProp.tel[i].number));
} else {
this.tel = null;
}
this.org = _create(aProp.org) || null;
this.jobTitle = _create(aProp.jobTitle) || null;
this.bday = (aProp.bday == "undefined" || aProp.bday == null) ? null : new Date(aProp.bday);
this.note = _create(aProp.note) || null;
this.impp = _create(aProp.impp) || null;
@ -157,7 +189,7 @@ Contact.prototype = {
get updated () {
return this._updated;
},
set updated(aUpdated) {
this._updated = aUpdated;
},
@ -218,6 +250,7 @@ ContactManager.prototype = {
adr: [],
tel: [],
org: [],
jobTitle: [],
bday: null,
note: [],
impp: [],
@ -352,9 +385,9 @@ ContactManager.prototype = {
return null;
this.initHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
"Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
"Contact:Save:Return:OK", "Contact:Save:Return:KO",
"Contact:Remove:Return:OK", "Contact:Remove:Return:KO"]);
"Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
"Contact:Save:Return:OK", "Contact:Save:Return:KO",
"Contact:Remove:Return:OK", "Contact:Remove:Return:KO"]);
let principal = aWindow.document.nodePrincipal;
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
@ -412,4 +445,5 @@ MozContactEvent.prototype = {
classDescription: "Contact Change Event"})
}
const NSGetFactory = XPCOMUtils.generateNSGetFactory([Contact, ContactManager, ContactProperties, ContactAddress, ContactFindOptions])
const NSGetFactory = XPCOMUtils.generateNSGetFactory(
[Contact, ContactManager, ContactProperties, ContactAddress, ContactTelephone, ContactFindOptions])

View File

@ -1,8 +1,11 @@
component {53ed7c20-ceda-11e0-9572-0800200c9a66} ContactManager.js
contract @mozilla.org/contactProperties;1 {53ed7c20-ceda-11e0-9572-0800200c9a66}
component {f5181640-89e8-11e1-b0c4-0800200c9a66} ContactManager.js
contract @mozilla.org/contactProperties;1 {f5181640-89e8-11e1-b0c4-0800200c9a66}
component {27a568b0-cee1-11e0-9572-0800200c9a66} ContactManager.js
contract @mozilla.org/contactAddress;1 {27a568b0-cee1-11e0-9572-0800200c9a66}
component {eba48030-89e8-11e1-b0c4-0800200c9a66} ContactManager.js
contract @mozilla.org/contactAddress;1 {eba48030-89e8-11e1-b0c4-0800200c9a66}
component {82601b20-89e8-11e1-b0c4-0800200c9a66} ContactManager.js
contract @mozilla.org/contactTelephone;1 {82601b20-89e8-11e1-b0c4-0800200c9a66}
component {e31daea0-0cb6-11e1-be50-0800200c9a66} ContactManager.js
contract @mozilla.org/contactFindOptions;1 {e31daea0-0cb6-11e1-be50-0800200c9a66}

View File

@ -22,7 +22,7 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
const DB_NAME = "contacts";
const DB_VERSION = 1;
const DB_VERSION = 2;
const STORE_NAME = "contacts";
function ContactDB(aGlobal) {
@ -32,42 +32,77 @@ function ContactDB(aGlobal) {
ContactDB.prototype = {
__proto__: IndexedDBHelper.prototype,
/**
* Create the initial database schema.
*
* The schema of records stored is as follows:
*
* {id: "...", // UUID
* published: Date(...), // First published date.
* updated: Date(...), // Last updated date.
* properties: {...} // Object holding the ContactProperties
* }
*/
createSchema: function createSchema(db) {
let objectStore = db.createObjectStore(this.dbStoreName, {keyPath: "id"});
// Metadata indexes
objectStore.createIndex("published", "published", { unique: false });
objectStore.createIndex("updated", "updated", { unique: false });
upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
let db = aDb;
let objectStore;
for (let currVersion = aOldVersion; currVersion < aNewVersion; currVersion++) {
if (currVersion == 0) {
/**
* Create the initial database schema.
*
* The schema of records stored is as follows:
*
* {id: "...", // UUID
* published: Date(...), // First published date.
* updated: Date(...), // Last updated date.
* properties: {...} // Object holding the ContactProperties
* }
*/
debug("create schema");
objectStore = db.createObjectStore(this.dbStoreName, {keyPath: "id"});
// Properties indexes
objectStore.createIndex("nickname", "properties.nickname", { unique: false, multiEntry: true });
objectStore.createIndex("name", "properties.name", { unique: false, multiEntry: true });
objectStore.createIndex("familyName", "properties.familyName", { unique: false, multiEntry: true });
objectStore.createIndex("givenName", "properties.givenName", { unique: false, multiEntry: true });
objectStore.createIndex("tel", "properties.tel", { unique: false, multiEntry: true });
objectStore.createIndex("email", "properties.email", { unique: false, multiEntry: true });
objectStore.createIndex("note", "properties.note", { unique: false, multiEntry: true });
// Metadata indexes
objectStore.createIndex("published", "published", { unique: false });
objectStore.createIndex("updated", "updated", { unique: false });
objectStore.createIndex("nicknameLowerCase", "search.nickname", { unique: false, multiEntry: true });
objectStore.createIndex("nameLowerCase", "search.name", { unique: false, multiEntry: true });
objectStore.createIndex("familyNameLowerCase", "search.familyName", { unique: false, multiEntry: true });
objectStore.createIndex("givenNameLowerCase", "search.givenName", { unique: false, multiEntry: true });
objectStore.createIndex("telLowerCase", "search.tel", { unique: false, multiEntry: true });
objectStore.createIndex("emailLowerCase", "search.email", { unique: false, multiEntry: true });
objectStore.createIndex("noteLowerCase", "search.note", { unique: false, multiEntry: true });
// Properties indexes
objectStore.createIndex("nickname", "properties.nickname", { unique: false, multiEntry: true });
objectStore.createIndex("name", "properties.name", { unique: false, multiEntry: true });
objectStore.createIndex("familyName", "properties.familyName", { unique: false, multiEntry: true });
objectStore.createIndex("givenName", "properties.givenName", { unique: false, multiEntry: true });
objectStore.createIndex("tel", "properties.tel", { unique: false, multiEntry: true });
objectStore.createIndex("email", "properties.email", { unique: false, multiEntry: true });
objectStore.createIndex("note", "properties.note", { unique: false, multiEntry: true });
debug("Created object stores and indexes");
objectStore.createIndex("nicknameLowerCase", "search.nickname", { unique: false, multiEntry: true });
objectStore.createIndex("nameLowerCase", "search.name", { unique: false, multiEntry: true });
objectStore.createIndex("familyNameLowerCase", "search.familyName", { unique: false, multiEntry: true });
objectStore.createIndex("givenNameLowerCase", "search.givenName", { unique: false, multiEntry: true });
objectStore.createIndex("telLowerCase", "search.tel", { unique: false, multiEntry: true });
objectStore.createIndex("emailLowerCase", "search.email", { unique: false, multiEntry: true });
objectStore.createIndex("noteLowerCase", "search.note", { unique: false, multiEntry: true });
} else if (currVersion == 1) {
debug("upgrade 1");
// Create a new scheme for the tel field. We move from an array of tel-numbers to an array of
// ContactTelephone.
if (!objectStore) {
objectStore = aTransaction.objectStore(STORE_NAME);
}
// Delete old tel index.
objectStore.deleteIndex("tel");
// Upgrade existing tel field in the DB.
objectStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
debug("upgrade tel1: " + JSON.stringify(cursor.value));
for (let number in cursor.value.properties.tel) {
cursor.value.properties.tel[number] = {number: number};
}
cursor.update(cursor.value);
debug("upgrade tel2: " + JSON.stringify(cursor.value));
cursor.continue();
}
};
// Create new searchable indexes.
objectStore.createIndex("tel", "search.tel", { unique: false, multiEntry: true });
objectStore.createIndex("category", "properties.category", { unique: false, multiEntry: true });
}
}
},
makeImport: function makeImport(aContact) {
@ -87,6 +122,7 @@ ContactDB.prototype = {
adr: [],
tel: [],
org: [],
jobTitle: [],
bday: null,
note: [],
impp: [],
@ -107,6 +143,7 @@ ContactDB.prototype = {
category: [],
tel: [],
org: [],
jobTitle: [],
note: [],
impp: []
};
@ -122,7 +159,7 @@ ContactDB.prototype = {
// "+1-234-567" should also be found with 1234, 234-56, 23456
// Chop off the first characters
let number = aContact.properties[field][i];
let number = aContact.properties[field][i].number;
for(let i = 0; i < number.length; i++) {
contact.search[field].push(number.substring(i, number.length));
}
@ -229,11 +266,6 @@ ContactDB.prototype = {
* - filterOp
* - filterValue
* - count
* Possibly supported in the future:
* - fields
* - sortBy
* - sortOrder
* - startIndex
*/
find: function find(aSuccessCb, aFailureCb, aOptions) {
debug("ContactDB:find val:" + aOptions.filterValue + " by: " + aOptions.filterBy + " op: " + aOptions.filterOp + "\n");
@ -277,6 +309,9 @@ ContactDB.prototype = {
if (key == "id") {
// store.get would return an object and not an array
request = store.getAll(options.filterValue);
} else if (key == "category") {
let index = store.index(key);
request = index.getAll(options.filterValue, limit);
} else if (options.filterOp == "equals") {
debug("Getting index: " + key);
// case sensitive

View File

@ -73,7 +73,7 @@ let DOMContactManager = {
if (b.properties[msg.findOptions.sortBy])
y = b.properties[msg.findOptions.sortBy][0].toLowerCase();
let result = x.localeCompare(y);
return msg.findOptions.sortOrder == 'ascending' ? result : -result;
return msg.findOptions.sortOrder == 'ascending' ? result : -result;
}
debug("Fallback DOMContactManager::receiveMessage " + aMessage.name);
let msg = aMessage.json;

View File

@ -58,6 +58,7 @@ var c5 = {
};
var adr1 = {
type: "work",
streetAddress: "street 1",
locality: "locality 1",
region: "region 1",
@ -66,6 +67,7 @@ var adr1 = {
};
var adr2 = {
type: "home, fax",
streetAddress: "street2",
locality: "locality2",
region: "region2",
@ -78,7 +80,7 @@ var properties1 = {
familyName: ["TestFamilyName","Wagner"],
givenName: ["Test1","Test2"],
nickname: "nicktest",
tel: ["123456", "+9-876-5432"],
tel: [{type: "work", number: "123456"} , {type: "home", number: "+9-876-5432"}],
adr: adr1
};
@ -90,11 +92,12 @@ var properties2 = {
honorificSuffix: "dummyHonorificSuffix",
additionalName: "dummyadditionalName",
nickname: "dummyNickname",
tel: ["123456789", "234567890"],
tel: [{type: "test", number: "123456789"},{type: "home", number: "234567890"}],
email: ["a@b.c", "b@c.d"],
adr: [adr1, adr2],
impp: ["im1", "im2"],
org: ["org1", "org2"],
jobTitle: ["boss", "superboss"],
bday: new Date("1980, 12, 01"),
note: "test note",
photo: ["pic1", "pic2"],
@ -137,6 +140,7 @@ function checkStr(str1, str2, msg) {
}
function checkAddress(adr1, adr2) {
checkStr(adr1.type, adr2.type, "Same type");
checkStr(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
checkStr(adr1.locality, adr2.locality, "Same locality");
checkStr(adr1.region, adr2.region, "Same region");
@ -144,6 +148,11 @@ function checkAddress(adr1, adr2) {
checkStr(adr1.countryName, adr2.countryName, "Same countryName");
}
function checkTel(tel1, tel2) {
checkStr(tel1.type, tel2.type, "Same type");
checkStr(tel1.number, tel2.number, "Same number");
}
function checkContacts(contact1, contact2) {
checkStr(contact1.name, contact2.name, "Same name");
checkStr(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
@ -156,6 +165,8 @@ function checkContacts(contact1, contact2) {
checkStr(contact1.photo, contact2.photo, "Same photo");
checkStr(contact1.url, contact2.url, "Same url");
checkStr(contact1.category, contact2.category, "Same category");
checkStr(contact1.org, contact2.org, "Same org");
checkStr(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
checkStr(contact1.note, contact2.note, "Same note");
checkStr(contact1.impp, contact2.impp, "Same impp");
@ -165,6 +176,8 @@ function checkContacts(contact1, contact2) {
for (var i in contact1.adr)
checkAddress(contact1.adr[i], contact2.adr[i]);
for (var i in contact1.tel)
checkTel(contact1.tel[i], contact2.tel[i]);
}
var req;
@ -388,7 +401,7 @@ var steps = [
ok(true, "Retrieving by substring tel1");
var options = {filterBy: ["tel"],
filterOp: "contains",
filterValue: properties1.tel[1].substring(1,5)};
filterValue: properties1.tel[1].number.substring(1,5)};
mozContacts.oncontactchange = null;
req = mozContacts.find(options);
req.onsuccess = function () {
@ -724,7 +737,7 @@ var steps = [
ok(true, "Searching contacts by tel");
var options = {filterBy: ["tel"],
filterOp: "contains",
filterValue: properties2.tel[0].substring(0, 7)};
filterValue: properties2.tel[0].number.substring(0, 7)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");
@ -890,7 +903,7 @@ var steps = [
function () {
ok(true, "Search with redundant fields should only return 1 contact");
createResult1 = new mozContact();
createResult1.init({name: "XXX", nickname: "XXX", email: "XXX", tel: "XXX"});
createResult1.init({name: "XXX", nickname: "XXX", email: "XXX", tel: {number: "XXX"}});
req = mozContacts.save(createResult1);
req.onsuccess = function() {
var options = {filterBy: [],
@ -1020,6 +1033,73 @@ var steps = [
};
req.onerror = onFailure;
},
function () {
ok(true, "Don't allow to add custom fields");
createResult1 = new mozContact();
createResult1.init({name: "customTest", yyy: "XXX"});
req = mozContacts.save(createResult1);
req.onsuccess = function() {
var options = {filterBy: [],
filterOp: "equals",
filterValue: "customTest"};
var req2 = mozContacts.find(options);
req2.onsuccess = function() {
ok(req2.result.length == 1, "1 Entry");
checkStr(req2.result.name, "customTest", "same name");
ok(req2.result.yyy === undefined, "custom property undefined");
next();
}
req2.onerror = onFailure;
}
req.onerror = onFailure;
},
function () {
ok(true, "Deleting database");
req = mozContacts.clear()
req.onsuccess = function () {
ok(true, "Deleted the database");
next();
}
req.onerror = onFailure;
},
function () {
ok(true, "Adding a new contact with properties2");
createResult2 = new mozContact();
createResult2.init(properties2);
req = mozContacts.save(createResult2);
req.onsuccess = function () {
ok(createResult2.id, "The contact now has an ID.");
sample_id2 = createResult2.id;
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Test category search with contains");
var options = {filterBy: ["category"],
filterOp: "contains",
filterValue: properties2.category[0]};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "1 Entry.");
checkContacts(req.result[0], createResult2);
next();
}
req.onerror = onFailure;
},
function () {
ok(true, "Test category search with equals");
var options = {filterBy: ["category"],
filterOp: "equals",
filterValue: properties2.category[0]};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "1 Entry.");
checkContacts(req.result[0], createResult2);
next();
}
req.onerror = onFailure;
},
function () {
ok(true, "Deleting database");
req = mozContacts.clear()

View File

@ -7,9 +7,10 @@
interface nsIArray;
interface nsIDOMContact;
[scriptable, uuid(27a568b0-cee1-11e0-9572-0800200c9a66)]
[scriptable, uuid(eba48030-89e8-11e1-b0c4-0800200c9a66)]
interface nsIDOMContactAddress : nsISupports
{
attribute DOMString type;
attribute DOMString streetAddress;
attribute DOMString locality;
attribute DOMString region;
@ -17,6 +18,13 @@ interface nsIDOMContactAddress : nsISupports
attribute DOMString countryName;
};
[scriptable, uuid(82601b20-89e8-11e1-b0c4-0800200c9a66)]
interface nsIDOMContactTelephone : nsISupports
{
attribute DOMString type;
attribute DOMString number;
};
[scriptable, uuid(e31daea0-0cb6-11e1-be50-0800200c9a66)]
interface nsIDOMContactFindOptions : nsISupports
{
@ -28,7 +36,7 @@ interface nsIDOMContactFindOptions : nsISupports
attribute unsigned long filterLimit;
};
[scriptable, uuid(53ed7c20-ceda-11e0-9572-0800200c9a66)]
[scriptable, uuid(f5181640-89e8-11e1-b0c4-0800200c9a66)]
interface nsIDOMContactProperties : nsISupports
{
attribute jsval name; // DOMString[]
@ -43,8 +51,9 @@ interface nsIDOMContactProperties : nsISupports
attribute jsval url; // DOMString[]
attribute jsval category; // DOMString[]
attribute jsval adr; // ContactAddress[]
attribute jsval tel; // DOMString[]
attribute jsval tel; // ContactTelephone[]
attribute jsval org; // DOMString[]
attribute jsval jobTitle; // DOMString[]
attribute jsval bday; // Date
attribute jsval note; // DOMString[]
attribute jsval impp; // DOMString[]

View File

@ -24,7 +24,7 @@ SettingsDB.prototype = {
__proto__: IndexedDBHelper.prototype,
createSchema: function createSchema(aDb) {
upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
let objectStore = aDb.createObjectStore(SETTINGSSTORE_NAME, { keyPath: "settingName" });
objectStore.createIndex("settingValue", "settingValue", { unique: false });
debug("Created object stores and indexes");