зеркало из https://github.com/mozilla/gecko-dev.git
Bug 836519 - Back out 7a145f17e37c for intermittent 'dom/contacts/tests/test_contacts_getall.html | 19 contacts returned - got 20, expected 19' in the test it added. r=intermittent-orange
This commit is contained in:
Родитель
42e294f8cb
Коммит
3d6315d338
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
"use strict"
|
||||
|
||||
let DEBUG = 0;
|
||||
let debug;
|
||||
|
@ -49,7 +49,7 @@ IndexedDBHelper.prototype = {
|
|||
if (DEBUG) debug("Try to open database:" + self.dbName + " " + self.dbVersion);
|
||||
let req = this.dbGlobal.indexedDB.open(this.dbName, this.dbVersion);
|
||||
req.onsuccess = function (event) {
|
||||
if (DEBUG) debug("Opened database:" + self.dbName + " " + self.dbVersion);
|
||||
if (DEBUG) debug("Opened database:" + self.dbName + " " + self.dbName);
|
||||
self._db = event.target.result;
|
||||
self._db.onversionchange = function(event) {
|
||||
if (DEBUG) debug("WARNING: DB modified from a different window.");
|
||||
|
@ -60,7 +60,7 @@ IndexedDBHelper.prototype = {
|
|||
req.onupgradeneeded = function (aEvent) {
|
||||
if (DEBUG) {
|
||||
debug("Database needs upgrade:" + self.dbName + aEvent.oldVersion + aEvent.newVersion);
|
||||
debug("Correct new database version:" + (aEvent.newVersion == this.dbVersion));
|
||||
debug("Correct new database version:" + aEvent.newVersion == this.dbVersion);
|
||||
}
|
||||
|
||||
let _db = aEvent.target.result;
|
||||
|
@ -117,9 +117,7 @@ IndexedDBHelper.prototype = {
|
|||
|
||||
txn.oncomplete = function (event) {
|
||||
if (DEBUG) debug("Transaction complete. Returning to callback.");
|
||||
if (successCb) {
|
||||
successCb(txn.result);
|
||||
}
|
||||
successCb(txn.result);
|
||||
};
|
||||
|
||||
txn.onabort = function (event) {
|
||||
|
@ -128,13 +126,10 @@ IndexedDBHelper.prototype = {
|
|||
* event.target.error may be null
|
||||
* if txn was aborted by calling txn.abort()
|
||||
*/
|
||||
if (failureCb) {
|
||||
if (event.target.error) {
|
||||
if (event.target.error)
|
||||
failureCb(event.target.error.name);
|
||||
} else {
|
||||
else
|
||||
failureCb("UnknownError");
|
||||
}
|
||||
}
|
||||
};
|
||||
callback(txn, store);
|
||||
}.bind(this), failureCb);
|
||||
|
|
|
@ -134,24 +134,6 @@ ContactTelField.prototype = {
|
|||
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactTelField])
|
||||
}
|
||||
|
||||
//ContactFindSortOptions
|
||||
|
||||
const CONTACTFINDSORTOPTIONS_CONTRACTID = "@mozilla.org/contactFindSortOptions;1"
|
||||
const CONTACTFINDSORTOPTIONS_CID = Components.ID("{cb008c06-3bf8-495c-8865-f9ca1673a1e1}");
|
||||
const nsIDOMContactFindSortOptions = Ci.nsIDOMContactFindSortOptions;
|
||||
|
||||
function ContactFindSortOptions () { }
|
||||
|
||||
ContactFindSortOptions.prototype = {
|
||||
classID: CONTACTFINDSORTOPTIONS_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: CONTACTFINDSORTOPTIONS_CID,
|
||||
contractID: CONTACTFINDSORTOPTIONS_CONTRACTID,
|
||||
classDescription: "ContactFindSortOptions",
|
||||
interfaces: [nsIDOMContactFindSortOptions],
|
||||
flags: nsIClassInfo.DOM_OBJECT}),
|
||||
QueryInterface: XPCOMUtils.generateQI([nsIDOMContactFindSortOptions])
|
||||
};
|
||||
|
||||
//ContactFindOptions
|
||||
|
||||
const CONTACTFINDOPTIONS_CONTRACTID = "@mozilla.org/contactFindOptions;1";
|
||||
|
@ -166,12 +148,10 @@ ContactFindOptions.prototype = {
|
|||
classInfo : XPCOMUtils.generateCI({classID: CONTACTFINDOPTIONS_CID,
|
||||
contractID: CONTACTFINDOPTIONS_CONTRACTID,
|
||||
classDescription: "ContactFindOptions",
|
||||
interfaces: [nsIDOMContactFindSortOptions,
|
||||
nsIDOMContactFindOptions],
|
||||
interfaces: [nsIDOMContactFindOptions],
|
||||
flags: nsIClassInfo.DOM_OBJECT}),
|
||||
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactFindSortOptions,
|
||||
nsIDOMContactFindOptions])
|
||||
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactFindOptions])
|
||||
}
|
||||
|
||||
//Contact
|
||||
|
@ -212,10 +192,10 @@ Contact.prototype = {
|
|||
|
||||
init: function init(aProp) {
|
||||
// Accept non-array strings for DOMString[] properties and convert them.
|
||||
function _create(aField) {
|
||||
function _create(aField) {
|
||||
if (Array.isArray(aField)) {
|
||||
for (let i = 0; i < aField.length; i++) {
|
||||
if (typeof aField[i] != "string")
|
||||
if (typeof aField[i] !== "string")
|
||||
aField[i] = String(aField[i]);
|
||||
}
|
||||
return aField;
|
||||
|
@ -337,7 +317,7 @@ Contact.prototype = {
|
|||
// ContactManager
|
||||
|
||||
const CONTACTMANAGER_CONTRACTID = "@mozilla.org/contactManager;1";
|
||||
const CONTACTMANAGER_CID = Components.ID("{1d70322b-f11b-4f19-9586-7bf291f212aa}");
|
||||
const CONTACTMANAGER_CID = Components.ID("{d88af7e0-a45f-11e1-b3dd-0800200c9a66}");
|
||||
const nsIDOMContactManager = Components.interfaces.nsIDOMContactManager;
|
||||
|
||||
function ContactManager()
|
||||
|
@ -349,8 +329,6 @@ ContactManager.prototype = {
|
|||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
_oncontactchange: null,
|
||||
|
||||
_cursorData: {},
|
||||
|
||||
set oncontactchange(aCallback) {
|
||||
if (DEBUG) debug("set oncontactchange");
|
||||
let allowCallback = function() {
|
||||
|
@ -375,23 +353,19 @@ ContactManager.prototype = {
|
|||
aNewContact.updated = aRecord.updated;
|
||||
},
|
||||
|
||||
_convertContact: function CM_convertContact(aContact) {
|
||||
let newContact = new Contact();
|
||||
newContact.init(aContact.properties);
|
||||
this._setMetaData(newContact, aContact);
|
||||
return newContact;
|
||||
},
|
||||
|
||||
_convertContacts: function(aContacts) {
|
||||
let contacts = [];
|
||||
_convertContactsArray: function(aContacts) {
|
||||
let contacts = new Array();
|
||||
for (let i in aContacts) {
|
||||
contacts.push(this._convertContact(aContacts[i]));
|
||||
let newContact = new Contact();
|
||||
newContact.init(aContacts[i].properties);
|
||||
this._setMetaData(newContact, aContacts[i]);
|
||||
contacts.push(newContact);
|
||||
}
|
||||
return contacts;
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
if (DEBUG) debug("receiveMessage: " + aMessage.name);
|
||||
if (DEBUG) debug("Contactmanager::receiveMessage: " + aMessage.name);
|
||||
let msg = aMessage.json;
|
||||
let contacts = msg.contacts;
|
||||
|
||||
|
@ -400,21 +374,12 @@ ContactManager.prototype = {
|
|||
case "Contacts:Find:Return:OK":
|
||||
req = this.getRequest(msg.requestID);
|
||||
if (req) {
|
||||
let result = this._convertContacts(contacts);
|
||||
let result = this._convertContactsArray(contacts);
|
||||
Services.DOMRequest.fireSuccess(req.request, result);
|
||||
} else {
|
||||
if (DEBUG) debug("no request stored!" + msg.requestID);
|
||||
}
|
||||
break;
|
||||
case "Contacts:GetAll:Next":
|
||||
let cursor = this._cursorData[msg.cursorId];
|
||||
let contact = msg.contact ? this._convertContact(msg.contact) : null;
|
||||
if (contact == null) {
|
||||
Services.DOMRequest.fireDone(cursor);
|
||||
} else {
|
||||
Services.DOMRequest.fireSuccess(cursor, contact);
|
||||
}
|
||||
break;
|
||||
case "Contacts:GetSimContacts:Return:OK":
|
||||
req = this.getRequest(msg.requestID);
|
||||
if (req) {
|
||||
|
@ -500,7 +465,7 @@ ContactManager.prototype = {
|
|||
default:
|
||||
access = "unknown";
|
||||
}
|
||||
|
||||
|
||||
let requestID = this.getRequestId({
|
||||
request: aRequest,
|
||||
allow: function() {
|
||||
|
@ -580,7 +545,8 @@ ContactManager.prototype = {
|
|||
|
||||
find: function(aOptions) {
|
||||
if (DEBUG) debug("find! " + JSON.stringify(aOptions));
|
||||
let request = this.createRequest();
|
||||
let request;
|
||||
request = this.createRequest();
|
||||
let options = { findOptions: aOptions };
|
||||
let allowCallback = function() {
|
||||
cpmm.sendAsyncMessage("Contacts:Find", {requestID: this.getRequestId({request: request, reason: "find"}), options: options});
|
||||
|
@ -589,34 +555,6 @@ ContactManager.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
createCursor: function CM_createCursor(aRequest) {
|
||||
let id = this._getRandomId();
|
||||
let cursor = Services.DOMRequest.createCursor(this._window, function() {
|
||||
this.handleContinue(id);
|
||||
}.bind(this));
|
||||
if (DEBUG) debug("saved cursor id: " + id);
|
||||
this._cursorData[id] = cursor;
|
||||
return [id, cursor];
|
||||
},
|
||||
|
||||
getAll: function CM_getAll(aOptions) {
|
||||
if (DEBUG) debug("getAll: " + JSON.stringify(aOptions));
|
||||
let [cursorId, cursor] = this.createCursor();
|
||||
let allowCallback = function() {
|
||||
cpmm.sendAsyncMessage("Contacts:GetAll", {
|
||||
cursorId: cursorId, findOptions: aOptions});
|
||||
}.bind(this);
|
||||
this.askPermission("find", cursor, allowCallback);
|
||||
return cursor;
|
||||
},
|
||||
|
||||
handleContinue: function CM_handleContinue(aCursorId) {
|
||||
if (DEBUG) debug("handleContinue: " + aCursorId);
|
||||
cpmm.sendAsyncMessage("Contacts:GetAll:Continue", {
|
||||
cursorId: aCursorId
|
||||
});
|
||||
},
|
||||
|
||||
remove: function removeContact(aRecord) {
|
||||
let request;
|
||||
request = this.createRequest();
|
||||
|
@ -671,8 +609,7 @@ ContactManager.prototype = {
|
|||
"Contacts:GetSimContacts:Return:OK",
|
||||
"Contacts:GetSimContacts:Return:KO",
|
||||
"Contact:Changed",
|
||||
"PermissionPromptHelper:AskPermission:OK",
|
||||
"Contacts:GetAll:Next"]);
|
||||
"PermissionPromptHelper:AskPermission:OK"]);
|
||||
},
|
||||
|
||||
// Called from DOMRequestIpcHelper
|
||||
|
@ -693,4 +630,4 @@ ContactManager.prototype = {
|
|||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
|
||||
[Contact, ContactManager, ContactProperties, ContactAddress, ContactField, ContactTelField, ContactFindSortOptions, ContactFindOptions])
|
||||
[Contact, ContactManager, ContactProperties, ContactAddress, ContactField, ContactTelField, ContactFindOptions])
|
||||
|
|
|
@ -10,16 +10,13 @@ contract @mozilla.org/contactField;1 {e2cb19c0-e4aa-11e1-9b23-0800200c9a66}
|
|||
component {ed0ab260-e4aa-11e1-9b23-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contactTelField;1 {ed0ab260-e4aa-11e1-9b23-0800200c9a66}
|
||||
|
||||
component {cb008c06-3bf8-495c-8865-f9ca1673a1e1} ContactManager.js
|
||||
contract @mozilla.org/contactFindSortOptions;1 {cb008c06-3bf8-495c-8865-f9ca1673a1e1}
|
||||
|
||||
component {e13ca4c5-c9cd-40bb-95e9-b636d42f5edf} ContactManager.js
|
||||
contract @mozilla.org/contactFindOptions;1 {e13ca4c5-c9cd-40bb-95e9-b636d42f5edf}
|
||||
component {e31daea0-0cb6-11e1-be50-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contactFindOptions;1 {e31daea0-0cb6-11e1-be50-0800200c9a66}
|
||||
|
||||
component {da0f7040-388b-11e1-b86c-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contact;1 {da0f7040-388b-11e1-b86c-0800200c9a66}
|
||||
category JavaScript-global-constructor mozContact @mozilla.org/contact;1
|
||||
|
||||
component {1d70322b-f11b-4f19-9586-7bf291f212aa} ContactManager.js
|
||||
contract @mozilla.org/contactManager;1 {1d70322b-f11b-4f19-9586-7bf291f212aa}
|
||||
component {d88af7e0-a45f-11e1-b3dd-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contactManager;1 {d88af7e0-a45f-11e1-b3dd-0800200c9a66}
|
||||
category JavaScript-navigator-property mozContacts @mozilla.org/contactManager;1
|
||||
|
|
|
@ -18,9 +18,8 @@ Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
|||
Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
|
||||
|
||||
const DB_NAME = "contacts";
|
||||
const DB_VERSION = 8;
|
||||
const DB_VERSION = 7;
|
||||
const STORE_NAME = "contacts";
|
||||
const SAVED_GETALL_STORE_NAME = "getallcache";
|
||||
|
||||
this.ContactDB = function ContactDB(aGlobal) {
|
||||
if (DEBUG) debug("Constructor");
|
||||
|
@ -30,8 +29,6 @@ this.ContactDB = function ContactDB(aGlobal) {
|
|||
ContactDB.prototype = {
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
cursorData: {},
|
||||
|
||||
upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
|
||||
if (DEBUG) debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
|
||||
let db = aDb;
|
||||
|
@ -241,9 +238,6 @@ ContactDB.prototype = {
|
|||
objectStore.deleteIndex(names[i]);
|
||||
}
|
||||
}
|
||||
} else if (currVersion == 7) {
|
||||
if (DEBUG) debug("Adding object store for cached searches");
|
||||
db.createObjectStore(SAVED_GETALL_STORE_NAME);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -388,41 +382,6 @@ ContactDB.prototype = {
|
|||
record.updated = new Date();
|
||||
},
|
||||
|
||||
removeObjectFromCache: function CDB_removeObjectFromCache(aObjectId, aCallback) {
|
||||
if (DEBUG) debug("removeObjectFromCache: " + aObjectId);
|
||||
if (!aObjectId) {
|
||||
if (DEBUG) debug("No object ID passed");
|
||||
return;
|
||||
}
|
||||
this.newTxn("readwrite", SAVED_GETALL_STORE_NAME, function(txn, store) {
|
||||
store.openCursor().onsuccess = function(e) {
|
||||
let cursor = e.target.result;
|
||||
if (cursor) {
|
||||
for (let i = 0; i < cursor.value.length; ++i) {
|
||||
if (cursor.value[i] == aObjectId) {
|
||||
if (DEBUG) debug("id matches cache");
|
||||
cursor.value.splice(i, 1);
|
||||
cursor.update(cursor.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
aCallback();
|
||||
}
|
||||
}.bind(this);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// Invalidate the entire cache. It will be incrementally regenerated on demand
|
||||
// See getCacheForQuery
|
||||
invalidateCache: function CDB_invalidateCache() {
|
||||
if (DEBUG) debug("invalidate cache");
|
||||
this.newTxn("readwrite", SAVED_GETALL_STORE_NAME, function (txn, store) {
|
||||
store.clear();
|
||||
});
|
||||
},
|
||||
|
||||
saveContact: function saveContact(aContact, successCb, errorCb) {
|
||||
let contact = this.makeImport(aContact);
|
||||
this.newTxn("readwrite", STORE_NAME, function (txn, store) {
|
||||
|
@ -449,20 +408,15 @@ ContactDB.prototype = {
|
|||
store.put(contact);
|
||||
}
|
||||
}
|
||||
this.invalidateCache();
|
||||
}.bind(this);
|
||||
}.bind(this), successCb, errorCb);
|
||||
},
|
||||
|
||||
removeContact: function removeContact(aId, aSuccessCb, aErrorCb) {
|
||||
if (DEBUG) debug("removeContact: " + aId);
|
||||
this.removeObjectFromCache(aId, function() {
|
||||
this.newTxn("readwrite", STORE_NAME, function(txn, store) {
|
||||
store.delete(aId).onsuccess = function() {
|
||||
aSuccessCb();
|
||||
}
|
||||
}, null, aErrorCb);
|
||||
}.bind(this));
|
||||
this.newTxn("readwrite", STORE_NAME, function (txn, store) {
|
||||
if (DEBUG) debug("Going to delete" + aId);
|
||||
store.delete(aId);
|
||||
}, aSuccessCb, aErrorCb);
|
||||
},
|
||||
|
||||
clear: function clear(aSuccessCb, aErrorCb) {
|
||||
|
@ -472,164 +426,6 @@ ContactDB.prototype = {
|
|||
}, aSuccessCb, aErrorCb);
|
||||
},
|
||||
|
||||
getObjectById: function CDB_getObjectById(aStore, aObjectId, aCallback) {
|
||||
if (DEBUG) debug("getObjectById: " + aStore + ":" + aObjectId);
|
||||
this.newTxn("readonly", aStore, function (txn, store) {
|
||||
let req = store.get(aObjectId);
|
||||
req.onsuccess = function (event) {
|
||||
aCallback(event.target.result);
|
||||
};
|
||||
req.onerror = function (event) {
|
||||
aCallback(null);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
getCacheForQuery: function CDB_getCacheForQuery(aQuery, aCursorId, aSuccessCb) {
|
||||
if (DEBUG) debug("getCacheForQuery");
|
||||
// Here we try to get the cached results for query `aQuery'. If they don't
|
||||
// exist, it means the cache was invalidated and needs to be recreated, so
|
||||
// we do that. Otherwise, we just return the existing query.
|
||||
this.getObjectById(SAVED_GETALL_STORE_NAME, aQuery, function (aCache) {
|
||||
if (!aCache) {
|
||||
if (DEBUG) debug("creating cache for query " + aQuery);
|
||||
this.createCacheForQuery(aQuery, aCursorId, aSuccessCb);
|
||||
} else {
|
||||
if (DEBUG) debug("cache exists");
|
||||
if (!this.cursorData[aCursorId]) {
|
||||
this.cursorData[aCursorId] = aCache;
|
||||
}
|
||||
aSuccessCb(aCache);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
setCacheForQuery: function CDB_setCacheForQuery(aQuery, aCache, aCallback) {
|
||||
this.newTxn("readwrite", SAVED_GETALL_STORE_NAME, function (txn, store) {
|
||||
let req = store.put(aCache, aQuery);
|
||||
if (!aCallback) {
|
||||
return;
|
||||
}
|
||||
req.onsuccess = function () {
|
||||
aCallback(true);
|
||||
};
|
||||
req.onerror = function () {
|
||||
aCallback(false);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
createCacheForQuery: function CDB_createCacheForQuery(aQuery, aCursorId, aSuccessCb, aFailureCb) {
|
||||
this.find(function (aContacts) {
|
||||
if (aContacts) {
|
||||
let contactsArray = [];
|
||||
for (let i in aContacts) {
|
||||
contactsArray.push(aContacts[i].id);
|
||||
}
|
||||
|
||||
this.setCacheForQuery(aQuery, contactsArray);
|
||||
this.cursorData[aCursorId] = contactsArray;
|
||||
aSuccessCb(contactsArray);
|
||||
} else {
|
||||
aSuccessCb(null);
|
||||
}
|
||||
}.bind(this),
|
||||
function (aErrorMsg) { aFailureCb(aErrorMsg); },
|
||||
JSON.parse(aQuery));
|
||||
},
|
||||
|
||||
getAll: function CDB_getAll(aSuccessCb, aFailureCb, aOptions, aCursorId) {
|
||||
// Recreate the cache for this query if needed
|
||||
let optionStr = JSON.stringify(aOptions);
|
||||
this.getCacheForQuery(optionStr, aCursorId, function (aCachedResults) {
|
||||
if (aCachedResults && aCachedResults.length > 0) {
|
||||
if (DEBUG) debug("query returned at least one contact");
|
||||
this.getObjectById(STORE_NAME, aCachedResults[0], function (aContact) {
|
||||
this.cursorData[aCursorId].shift();
|
||||
aSuccessCb(aContact);
|
||||
}.bind(this));
|
||||
} else { // no contacts
|
||||
if (DEBUG) debug("query returned no contacts");
|
||||
aSuccessCb(null);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
getNext: function CDB_getNext(aSuccessCb, aFailureCb, aCursorId) {
|
||||
if (DEBUG) debug("ContactDB:getNext: " + aCursorId);
|
||||
let aCachedResults = this.cursorData[aCursorId];
|
||||
if (DEBUG) debug("got transient cache");
|
||||
if (aCachedResults.length > 0) {
|
||||
this.getObjectById(STORE_NAME, aCachedResults[0], function(aContact) {
|
||||
this.cursorData[aCursorId].shift();
|
||||
if (aContact) {
|
||||
aSuccessCb(aContact);
|
||||
} else {
|
||||
// If the contact ID in cache is invalid, it was removed recently and
|
||||
// the cache hasn't been updated to reflect the change, so we skip it.
|
||||
if (DEBUG) debug("invalid contact in cache: " + aCachedResults[0]);
|
||||
return this.getNext(aSuccessCb, aFailureCb, aCursorId);
|
||||
}
|
||||
}.bind(this));
|
||||
} else { // last contact
|
||||
delete this.cursorData[aCursorId];
|
||||
aSuccessCb(null);
|
||||
}
|
||||
},
|
||||
|
||||
releaseCursors: function CDB_releaseCursors(aCursors) {
|
||||
for (let i of aCursors) {
|
||||
delete this.cursorData[i];
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Sorting the contacts by sortBy field. aSortBy can either be familyName or givenName.
|
||||
* If 2 entries have the same sortyBy field or no sortBy field is present, we continue
|
||||
* sorting with the other sortyBy field.
|
||||
*/
|
||||
sortResults: function CDB_sortResults(aResults, aFindOptions) {
|
||||
if (!aFindOptions)
|
||||
return;
|
||||
if (aFindOptions.sortBy != "undefined") {
|
||||
aResults.sort(function (a, b) {
|
||||
let x, y;
|
||||
let result = 0;
|
||||
let sortOrder = aFindOptions.sortOrder;
|
||||
let sortBy = aFindOptions.sortBy == "familyName" ? [ "familyName", "givenName" ] : [ "givenName" , "familyName" ];
|
||||
let xIndex = 0;
|
||||
let yIndex = 0;
|
||||
|
||||
do {
|
||||
while (xIndex < sortBy.length && !x) {
|
||||
x = a.properties[sortBy[xIndex]] ? a.properties[sortBy[xIndex]][0].toLowerCase() : null;
|
||||
xIndex++;
|
||||
}
|
||||
if (!x) {
|
||||
return sortOrder == 'ascending' ? 1 : -1;
|
||||
}
|
||||
while (yIndex < sortBy.length && !y) {
|
||||
y = b.properties[sortBy[yIndex]] ? b.properties[sortBy[yIndex]][0].toLowerCase() : null;
|
||||
yIndex++;
|
||||
}
|
||||
if (!y) {
|
||||
return sortOrder == 'ascending' ? 1 : -1;
|
||||
}
|
||||
|
||||
result = x.localeCompare(y);
|
||||
x = null;
|
||||
y = null;
|
||||
} while (result == 0);
|
||||
|
||||
return sortOrder == 'ascending' ? result : -result;
|
||||
});
|
||||
}
|
||||
if (aFindOptions.filterLimit && aFindOptions.filterLimit != 0) {
|
||||
if (DEBUG) debug("filterLimit is set: " + aFindOptions.filterLimit);
|
||||
aResults.splice(aFindOptions.filterLimit, aResults.length);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param successCb
|
||||
* Callback function to invoke with result array.
|
||||
|
@ -643,7 +439,7 @@ ContactDB.prototype = {
|
|||
* - count
|
||||
*/
|
||||
find: function find(aSuccessCb, aFailureCb, aOptions) {
|
||||
if (DEBUG) debug("ContactDB:find val:" + aOptions.filterValue + " by: " + aOptions.filterBy + " op: " + aOptions.filterOp);
|
||||
if (DEBUG) debug("ContactDB:find val:" + aOptions.filterValue + " by: " + aOptions.filterBy + " op: " + aOptions.filterOp + "\n");
|
||||
let self = this;
|
||||
this.newTxn("readonly", STORE_NAME, function (txn, store) {
|
||||
if (aOptions && (aOptions.filterOp == "equals" || aOptions.filterOp == "contains")) {
|
||||
|
@ -659,7 +455,7 @@ ContactDB.prototype = {
|
|||
let fields = options.filterBy;
|
||||
for (let key in fields) {
|
||||
if (DEBUG) debug("key: " + fields[key]);
|
||||
if (!store.indexNames.contains(fields[key]) && fields[key] != "id") {
|
||||
if (!store.indexNames.contains(fields[key]) && !fields[key] == "id") {
|
||||
if (DEBUG) debug("Key not valid!" + fields[key] + ", " + store.indexNames);
|
||||
txn.abort();
|
||||
return;
|
||||
|
@ -710,8 +506,7 @@ ContactDB.prototype = {
|
|||
txn.result = {};
|
||||
|
||||
request.onsuccess = function (event) {
|
||||
if (DEBUG) debug("Request successful. Record count: " + event.target.result.length);
|
||||
this.sortResults(event.target.result, options);
|
||||
if (DEBUG) debug("Request successful. Record count:" + event.target.result.length);
|
||||
for (let i in event.target.result)
|
||||
txn.result[event.target.result[i].id] = this.makeExport(event.target.result[i]);
|
||||
}.bind(this);
|
||||
|
@ -725,15 +520,13 @@ ContactDB.prototype = {
|
|||
// Sorting functions takes care of limit if set.
|
||||
let limit = options.sortBy === 'undefined' ? options.filterLimit : null;
|
||||
store.mozGetAll(null, limit).onsuccess = function (event) {
|
||||
if (DEBUG) debug("Request successful. Record count:" + event.target.result.length);
|
||||
this.sortResults(event.target.result, options);
|
||||
for (let i in event.target.result) {
|
||||
if (DEBUG) debug("Request successful. Record count:", event.target.result.length);
|
||||
for (let i in event.target.result)
|
||||
txn.result[event.target.result[i].id] = this.makeExport(event.target.result[i]);
|
||||
}
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
init: function init(aGlobal) {
|
||||
this.initDBHelper(DB_NAME, DB_VERSION, [STORE_NAME, SAVED_GETALL_STORE_NAME], aGlobal);
|
||||
this.initDBHelper(DB_NAME, DB_VERSION, [STORE_NAME], aGlobal);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
const DEBUG = false;
|
||||
function debug(s) { dump("-*- Fallback ContactService component: " + s + "\n"); }
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
|
@ -37,18 +37,15 @@ XPCOMUtils.defineLazyGetter(this, "mRIL", function () {
|
|||
let myGlobal = this;
|
||||
|
||||
this.DOMContactManager = {
|
||||
// maps children to their live cursors so we can cleanup on shutdown/crash
|
||||
_liveCursors: {},
|
||||
|
||||
init: function() {
|
||||
if (DEBUG) debug("Init");
|
||||
this._messages = ["Contacts:Find", "Contacts:GetAll", "Contacts:GetAll:Continue", "Contacts:Clear", "Contact:Save",
|
||||
this._messages = ["Contacts:Find", "Contacts:Clear", "Contact:Save",
|
||||
"Contact:Remove", "Contacts:GetSimContacts",
|
||||
"Contacts:RegisterForMessages", "child-process-shutdown"];
|
||||
this._children = [];
|
||||
this._messages.forEach(function(msgName) {
|
||||
this._messages.forEach((function(msgName) {
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
}.bind(this));
|
||||
}).bind(this));
|
||||
|
||||
var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
|
||||
idbManager.initWindowless(myGlobal);
|
||||
|
@ -60,9 +57,9 @@ this.DOMContactManager = {
|
|||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
myGlobal = null;
|
||||
this._messages.forEach(function(msgName) {
|
||||
this._messages.forEach((function(msgName) {
|
||||
ppmm.removeMessageListener(msgName, this);
|
||||
}.bind(this));
|
||||
}).bind(this));
|
||||
Services.obs.removeObserver(this, "profile-before-change");
|
||||
ppmm = null;
|
||||
this._messages = null;
|
||||
|
@ -73,7 +70,7 @@ this.DOMContactManager = {
|
|||
|
||||
assertPermission: function(aMessage, aPerm) {
|
||||
if (!aMessage.target.assertPermission(aPerm)) {
|
||||
Cu.reportError("Contacts message " + aMessage.name +
|
||||
Cu.reportError("Contacts message " + msg.name +
|
||||
" from a content process with no" + aPerm + " privileges.");
|
||||
return false;
|
||||
}
|
||||
|
@ -87,56 +84,74 @@ this.DOMContactManager = {
|
|||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
if (DEBUG) debug("receiveMessage " + aMessage.name);
|
||||
if (DEBUG) debug("Fallback DOMContactManager::receiveMessage " + aMessage.name);
|
||||
let mm = aMessage.target;
|
||||
let msg = aMessage.data;
|
||||
|
||||
/*
|
||||
* Sorting the contacts by sortBy field. sortBy can either be familyName or givenName.
|
||||
* If 2 entries have the same sortyBy field or no sortBy field is present, we continue
|
||||
* sorting with the other sortyBy field.
|
||||
*/
|
||||
function sortfunction(a, b){
|
||||
let x, y;
|
||||
let result = 0;
|
||||
let findOptions = msg.options.findOptions;
|
||||
let sortOrder = findOptions.sortOrder;
|
||||
let sortBy = findOptions.sortBy === "familyName" ? [ "familyName", "givenName" ] : [ "givenName" , "familyName" ];
|
||||
let xIndex = 0;
|
||||
let yIndex = 0;
|
||||
|
||||
do {
|
||||
while (xIndex < sortBy.length && !x) {
|
||||
x = a.properties[sortBy[xIndex]] ? a.properties[sortBy[xIndex]][0].toLowerCase() : null;
|
||||
xIndex++;
|
||||
}
|
||||
if (!x) {
|
||||
return sortOrder == 'ascending' ? 1 : -1;
|
||||
}
|
||||
while (yIndex < sortBy.length && !y) {
|
||||
y = b.properties[sortBy[yIndex]] ? b.properties[sortBy[yIndex]][0].toLowerCase() : null;
|
||||
yIndex++;
|
||||
}
|
||||
if (!y) {
|
||||
return sortOrder == 'ascending' ? 1 : -1;
|
||||
}
|
||||
|
||||
result = x.localeCompare(y);
|
||||
x = null;
|
||||
y = null;
|
||||
} while (result === 0);
|
||||
|
||||
return sortOrder == 'ascending' ? result : -result;
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Contacts:Find":
|
||||
if (!this.assertPermission(aMessage, "contacts-read")) {
|
||||
return null;
|
||||
}
|
||||
let result = [];
|
||||
let result = new Array();
|
||||
this._db.find(
|
||||
function(contacts) {
|
||||
for (let i in contacts) {
|
||||
for (let i in contacts)
|
||||
result.push(contacts[i]);
|
||||
if (msg.options && msg.options.findOptions) {
|
||||
let findOptions = msg.options.findOptions;
|
||||
if (findOptions.sortOrder !== 'undefined' && findOptions.sortBy !== 'undefined') {
|
||||
if (DEBUG) debug('sortBy: ' + findOptions.sortBy + ', sortOrder: ' + findOptions.sortOrder );
|
||||
result.sort(sortfunction);
|
||||
if (findOptions.filterLimit)
|
||||
result = result.slice(0, findOptions.filterLimit);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) debug("result:" + JSON.stringify(result));
|
||||
mm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result});
|
||||
}.bind(this),
|
||||
function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this),
|
||||
function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this),
|
||||
msg.options.findOptions);
|
||||
break;
|
||||
case "Contacts:GetAll":
|
||||
if (!this.assertPermission(aMessage, "contacts-read")) {
|
||||
return null;
|
||||
}
|
||||
this._db.getAll(
|
||||
function(aContact) {
|
||||
mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contact: aContact});
|
||||
},
|
||||
function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Find:Return:KO", { errorMsg: aErrorMsg }); },
|
||||
msg.findOptions, msg.cursorId);
|
||||
if (Array.isArray(this._liveCursors[mm])) {
|
||||
this._liveCursors[mm].push(msg.cursorId);
|
||||
} else {
|
||||
this._liveCursors[mm] = [msg.cursorId];
|
||||
}
|
||||
break;
|
||||
case "Contacts:GetAll:Continue":
|
||||
this._db.getNext(
|
||||
function(aContact) {
|
||||
if (aContact == null) { // last contact, release the cursor
|
||||
let cursors = this._liveCursors[mm];
|
||||
cursors.splice(cursors.indexOf(msg.cursorId), 1);
|
||||
}
|
||||
mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contact: aContact});
|
||||
}.bind(this),
|
||||
function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Find:Return:KO", { errorMsg: aErrorMsg }); },
|
||||
msg.cursorId);
|
||||
break;
|
||||
case "Contact:Save":
|
||||
if (msg.options.reason === "create") {
|
||||
if (!this.assertPermission(aMessage, "contacts-create")) {
|
||||
|
@ -210,8 +225,6 @@ this.DOMContactManager = {
|
|||
break;
|
||||
case "child-process-shutdown":
|
||||
if (DEBUG) debug("Unregister");
|
||||
this._db.releaseCursors(this._liveCursors[mm]);
|
||||
delete this._liveCursors[mm];
|
||||
let index = this._children.indexOf(mm);
|
||||
if (index != -1) {
|
||||
if (DEBUG) debug("Unregister index: " + index);
|
||||
|
|
|
@ -19,7 +19,6 @@ MOCHITEST_FILES = \
|
|||
test_contacts_events.html \
|
||||
test_contacts_blobs.html \
|
||||
test_contacts_international.html \
|
||||
test_contacts_getall.html \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -1,422 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=836519
|
||||
-->
|
||||
<head>
|
||||
<title>Mozilla Bug 836519</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=836519">Mozilla Bug 836519</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
|
||||
"use strict";
|
||||
|
||||
// this shouldn't be necessary when bug 792594 is fixed
|
||||
if (!SpecialPowers.getBoolPref("dom.mozContacts.enabled")) {
|
||||
let comp = SpecialPowers.wrap(SpecialPowers.Components);
|
||||
comp.utils.import("resource://gre/modules/ContactService.jsm");
|
||||
comp.utils.import("resource://gre/modules/PermissionPromptHelper.jsm");
|
||||
SpecialPowers.setBoolPref("dom.mozContacts.enabled", true);
|
||||
}
|
||||
|
||||
SpecialPowers.addPermission("contacts-write", true, document);
|
||||
SpecialPowers.addPermission("contacts-read", true, document);
|
||||
SpecialPowers.addPermission("contacts-create", true, document);
|
||||
|
||||
let adr1 = {
|
||||
type: "work",
|
||||
streetAddress: "street 1",
|
||||
locality: "locality 1",
|
||||
region: "region 1",
|
||||
postalCode: "postal code 1",
|
||||
countryName: "country 1"
|
||||
};
|
||||
|
||||
let properties1 = {
|
||||
name: "Testname1",
|
||||
familyName: ["TestFamilyName","Wagner"],
|
||||
givenName: ["Test1","Test2"],
|
||||
nickname: "nicktest",
|
||||
tel: [{type: ["work"], value: "123456", carrier: "testCarrier"} , {type: ["home", "fax"], value: "+9-876-5432"}],
|
||||
adr: adr1,
|
||||
email: [{type: ["work"], value: "x@y.com"}]
|
||||
};
|
||||
|
||||
function onUnwantedSuccess() {
|
||||
ok(false, "onUnwantedSuccess: shouldn't get here");
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
ok(false, "in on Failure!");
|
||||
}
|
||||
|
||||
function checkStr(str1, str2, msg) {
|
||||
if (str1)
|
||||
ok(typeof str1 == "string" ? [str1] : str1, (typeof str2 == "string") ? [str2] : 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");
|
||||
checkStr(adr1.postalCode, adr2.postalCode, "Same postalCode");
|
||||
checkStr(adr1.countryName, adr2.countryName, "Same countryName");
|
||||
}
|
||||
|
||||
function checkTel(tel1, tel2) {
|
||||
checkStr(tel1.type, tel2.type, "Same type");
|
||||
checkStr(tel1.value, tel2.value, "Same value");
|
||||
checkStr(tel1.carrier, tel2.carrier, "Same carrier");
|
||||
}
|
||||
|
||||
function checkField(field1, field2) {
|
||||
checkStr(field1.type, field2.type, "Same type");
|
||||
checkStr(field1.value, field2.value, "Same value");
|
||||
}
|
||||
|
||||
function checkContacts(contact1, contact2) {
|
||||
checkStr(contact1.name, contact2.name, "Same name");
|
||||
checkStr(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
|
||||
checkStr(contact1.givenName, contact2.givenName, "Same givenName");
|
||||
checkStr(contact1.additionalName, contact2.additionalName, "Same additionalName");
|
||||
checkStr(contact1.familyName, contact2.familyName, "Same familyName");
|
||||
checkStr(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
|
||||
checkStr(contact1.nickname, contact2.nickname, "Same nickname");
|
||||
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");
|
||||
is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
|
||||
is(contact1.sex, contact2.sex, "Same sex");
|
||||
is(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
|
||||
|
||||
for (let i in contact1.email) {
|
||||
if (contact1.email) {
|
||||
ok(contact2.email != null, "conatct2.email exists");
|
||||
}
|
||||
if (contact2.email) {
|
||||
ok(contact1.email != null, "conatct1.email exists");
|
||||
}
|
||||
checkField(contact1.email[i], contact2.email[i]);
|
||||
}
|
||||
for (let i in contact1.adr) {
|
||||
if (contact1.adr) {
|
||||
ok(contact2.adr != null, "conatct2.adr exists");
|
||||
}
|
||||
if (contact2.adr) {
|
||||
ok(contact1.adr != null, "conatct1.adr exists");
|
||||
}
|
||||
checkAddress(contact1.adr[i], contact2.adr[i]);
|
||||
}
|
||||
for (let i in contact1.tel) {
|
||||
if (contact1.tel) {
|
||||
ok(contact2.tel != null, "conatct2.tel exists");
|
||||
}
|
||||
if (contact2.tel) {
|
||||
ok(contact1.tel != null, "conatct1.tel exists");
|
||||
}
|
||||
checkTel(contact1.tel[i], contact2.tel[i]);
|
||||
}
|
||||
for (let i in contact1.url) {
|
||||
if (contact1.url) {
|
||||
ok(contact2.url != null, "conatct2.url exists");
|
||||
}
|
||||
if (contact2.url) {
|
||||
ok(contact1.url != null, "conatct1.url exists");
|
||||
}
|
||||
checkField(contact1.url[i], contact2.url[i]);
|
||||
}
|
||||
for (let i in contact1.impp) {
|
||||
if (contact1.impp) {
|
||||
ok(contact2.impp != null, "conatct2.impp exists");
|
||||
}
|
||||
if (contact2.impp) {
|
||||
ok(contact1.impp != null, "conatct1.impp exists");
|
||||
}
|
||||
checkField(contact1.impp[i], contact2.impp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function clearDatabase() {
|
||||
ok(true, "Clearing database");
|
||||
req = mozContacts.clear();
|
||||
req.onsuccess = function() {
|
||||
ok(true, "Cleared the database");
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
}
|
||||
|
||||
function add20Contacts() {
|
||||
ok(true, "Adding 20 contacts");
|
||||
for (let i=0; i<19; i++) {
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init(properties1);
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = function() {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
};
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init(properties1);
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = function() {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
ok(createResult1.name == properties1.name, "Same Name");
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
}
|
||||
|
||||
let createResult1;
|
||||
|
||||
let index = 0;
|
||||
let req;
|
||||
let mozContacts = window.navigator.mozContacts;
|
||||
|
||||
let steps = [
|
||||
clearDatabase,
|
||||
function() {
|
||||
// add a contact
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init({});
|
||||
req = navigator.mozContacts.save(createResult1);
|
||||
req.onsuccess = function() {
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function() {
|
||||
ok(true, "Retrieving one contact with getAll");
|
||||
req = mozContacts.getAll({});
|
||||
let count = 0;
|
||||
req.onsuccess = function(event) {
|
||||
ok(true, "on success");
|
||||
if (req.result) {
|
||||
ok(true, "result is valid");
|
||||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 1, "last contact - only one contact returned");
|
||||
next();
|
||||
}
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
|
||||
function() {
|
||||
ok(true, "Retrieving 20 contacts with getAll");
|
||||
req = mozContacts.getAll({});
|
||||
let count = 0;
|
||||
req.onsuccess = function(event) {
|
||||
if (req.result) {
|
||||
ok(true, "result is valid");
|
||||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 20, "last contact - 20 contacts returned");
|
||||
next();
|
||||
}
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function() {
|
||||
ok(true, "Deleting one contact");
|
||||
req = mozContacts.remove(createResult1);
|
||||
req.onsuccess = function() {
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function() {
|
||||
ok(true, "Test cache invalidation");
|
||||
req = mozContacts.getAll({});
|
||||
let count = 0;
|
||||
req.onsuccess = function(event) {
|
||||
ok(true, "on success");
|
||||
if (req.result) {
|
||||
ok(true, "result is valid");
|
||||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 19, "last contact - 19 contacts returned");
|
||||
next();
|
||||
}
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
|
||||
function() {
|
||||
ok(true, "Test cache invalidation between getAll and getNext");
|
||||
req = mozContacts.getAll({});
|
||||
let count = 0;
|
||||
let firstResult = true;
|
||||
req.onsuccess = function(event) {
|
||||
ok(true, "on success");
|
||||
if (firstResult) {
|
||||
if (req.result) {
|
||||
count++;
|
||||
}
|
||||
let delReq = mozContacts.remove(createResult1);
|
||||
delReq.onsuccess = function() {
|
||||
firstResult = false;
|
||||
req.continue();
|
||||
};
|
||||
} else {
|
||||
if (req.result) {
|
||||
ok(true, "result is valid");
|
||||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 19, "19 contacts returned");
|
||||
ok(true, "last contact");
|
||||
next();
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
|
||||
function() {
|
||||
ok(true, "Delete the currect contact while iterating");
|
||||
req = mozContacts.getAll({});
|
||||
let count = 0;
|
||||
let previousId = null;
|
||||
req.onsuccess = function() {
|
||||
if (req.result) {
|
||||
ok(true, "on success");
|
||||
if (previousId) {
|
||||
isnot(previousId, req.result.id, "different contacts returned");
|
||||
}
|
||||
previousId = req.result.id;
|
||||
count++;
|
||||
let delReq = mozContacts.remove(req.result);
|
||||
delReq.onsuccess = function() {
|
||||
ok(true, "deleted current contact");
|
||||
req.continue();
|
||||
};
|
||||
} else {
|
||||
is(count, 20, "returned 20 contacts");
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
|
||||
function() {
|
||||
ok(true, "Iterating through the contact list inside a cursor callback");
|
||||
let count1 = 0, count2 = 0;
|
||||
let req1 = mozContacts.getAll({});
|
||||
let req2;
|
||||
req1.onsuccess = function() {
|
||||
if (count1 == 0) {
|
||||
count1++;
|
||||
req2 = mozContacts.getAll({});
|
||||
req2.onsuccess = function() {
|
||||
if (req2.result) {
|
||||
count2++;
|
||||
req2.continue();
|
||||
} else {
|
||||
is(count2, 20, "inner cursor returned 20 contacts");
|
||||
req1.continue();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
if (req1.result) {
|
||||
count1++;
|
||||
req1.continue();
|
||||
} else {
|
||||
is(count1, 20, "outer cursor returned 20 contacts");
|
||||
next();
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
clearDatabase,
|
||||
add20Contacts,
|
||||
|
||||
function() {
|
||||
ok(true, "20 concurrent cursors");
|
||||
const NUM_CURSORS = 20;
|
||||
let completed = 0;
|
||||
let createCursor = function(aNum) {
|
||||
let count = 0;
|
||||
let req = mozContacts.getAll({});
|
||||
req.onsuccess = function() {
|
||||
if (req.result) {
|
||||
count++;
|
||||
req.continue();
|
||||
} else {
|
||||
is(count, 20, "cursor " + aNum + " returned 20 contacts");
|
||||
if (++completed == NUM_CURSORS) {
|
||||
next();
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
}.bind(this);
|
||||
for (let i = 0; i < NUM_CURSORS; ++i) {
|
||||
createCursor(i);
|
||||
}
|
||||
},
|
||||
|
||||
clearDatabase,
|
||||
|
||||
function() {
|
||||
ok(true, "all done!\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
];
|
||||
|
||||
function next() {
|
||||
ok(true, "Begin!");
|
||||
if (index >= steps.length) {
|
||||
ok(false, "Shouldn't get here!");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
steps[index++]();
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
function permissionTest() {
|
||||
if (gContactsEnabled) {
|
||||
next();
|
||||
} else {
|
||||
is(mozContacts, null, "mozContacts is null when not enabled.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
let gContactsEnabled = SpecialPowers.getBoolPref("dom.mozContacts.enabled");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(permissionTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -7,11 +7,9 @@
|
|||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
interface nsIArray;
|
||||
interface nsIDOMContactFindSortOptions;
|
||||
interface nsIDOMContactFindOptions;
|
||||
interface nsIDOMContactProperties;
|
||||
interface nsIDOMDOMRequest;
|
||||
interface nsIDOMDOMCursor;
|
||||
|
||||
[scriptable, uuid(da0f7040-388b-11e1-b86c-0800200c9a66)]
|
||||
interface nsIDOMContact : nsIDOMContactProperties
|
||||
|
@ -23,17 +21,15 @@ interface nsIDOMContact : nsIDOMContactProperties
|
|||
void init(in nsIDOMContactProperties properties); // Workaround BUG 723206
|
||||
};
|
||||
|
||||
[scriptable, uuid(1d70322b-f11b-4f19-9586-7bf291f212aa)]
|
||||
[scriptable, uuid(d88af7e0-a45f-11e1-b3dd-0800200c9a66)]
|
||||
interface nsIDOMContactManager : nsISupports
|
||||
{
|
||||
nsIDOMDOMRequest find(in nsIDOMContactFindOptions options);
|
||||
|
||||
nsIDOMDOMCursor getAll(in nsIDOMContactFindSortOptions options);
|
||||
|
||||
nsIDOMDOMRequest clear();
|
||||
|
||||
nsIDOMDOMRequest save(in nsIDOMContact contact);
|
||||
|
||||
|
||||
nsIDOMDOMRequest remove(in nsIDOMContact contact);
|
||||
|
||||
nsIDOMDOMRequest getSimContacts(in DOMString type);
|
||||
|
|
|
@ -31,19 +31,14 @@ interface nsIDOMContactTelField : nsIDOMContactField
|
|||
attribute DOMString carrier;
|
||||
};
|
||||
|
||||
[scriptable, uuid(cb008c06-3bf8-495c-8865-f9ca1673a1e1)]
|
||||
interface nsIDOMContactFindSortOptions : nsISupports
|
||||
{
|
||||
attribute DOMString sortBy; // "givenName" or "familyName"
|
||||
attribute DOMString sortOrder; // e.g. "descending"
|
||||
};
|
||||
|
||||
[scriptable, uuid(e13ca4c5-c9cd-40bb-95e9-b636d42f5edf)]
|
||||
interface nsIDOMContactFindOptions : nsIDOMContactFindSortOptions
|
||||
[scriptable, uuid(e31daea0-0cb6-11e1-be50-0800200c9a66)]
|
||||
interface nsIDOMContactFindOptions : nsISupports
|
||||
{
|
||||
attribute DOMString filterValue; // e.g. "Tom"
|
||||
attribute DOMString filterOp; // e.g. "contains"
|
||||
attribute jsval filterBy; // DOMString[], e.g. ["givenName", "nickname"]
|
||||
attribute DOMString sortBy; // "givenName" or "familyName"
|
||||
attribute DOMString sortOrder; // e.g. "descending"
|
||||
attribute unsigned long filterLimit;
|
||||
};
|
||||
|
||||
|
|
|
@ -406,7 +406,6 @@ var interfaceNamesInGlobalScope =
|
|||
"XULMenuListElement",
|
||||
"SVGTransform",
|
||||
"SVGTextPositioningElement",
|
||||
"ContactFindSortOptions",
|
||||
"ContactFindOptions",
|
||||
"SVGFEMergeElement",
|
||||
"FileRequest",
|
||||
|
|
Загрузка…
Ссылка в новой задаче