Bug 750768 - Contacts API: add DB modification event. r=fabrice

This commit is contained in:
Gregor Wagner 2012-05-08 11:42:41 -07:00
parent cfaab91fe1
commit 4622a1fed5
6 changed files with 225 additions and 22 deletions

View File

@ -175,7 +175,7 @@ Contact.prototype = {
// ContactManager
const CONTACTMANAGER_CONTRACTID = "@mozilla.org/contactManager;1";
const CONTACTMANAGER_CID = Components.ID("{50a820b0-ced0-11e0-9572-0800200c9a66}");
const CONTACTMANAGER_CID = Components.ID("{d9ca0950-93d1-11e1-b0c4-0800200c9a66}");
const nsIDOMContactManager = Components.interfaces.nsIDOMContactManager;
function ContactManager()
@ -185,6 +185,18 @@ function ContactManager()
ContactManager.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
_oncontactchange: null,
set oncontactchange(aCallback) {
if (this.hasPrivileges)
this._oncontactchange = aCallback;
else
throw Components.results.NS_ERROR_FAILURE;
},
get oncontactchange() {
return this._oncontactchange;
},
save: function save(aContact) {
let request;
@ -216,17 +228,21 @@ ContactManager.prototype = {
for (let field in newContact.properties)
newContact.properties[field] = aContact[field];
let reason;
if (aContact.id == "undefined") {
// for example {25c00f01-90e5-c545-b4d4-21E2ddbab9e0} becomes
// 25c00f0190e5c545b4d421E2ddbab9e0
aContact.id = this._getRandomId().replace('-', '').replace('{', '').replace('}', '');
aContact.id = this._getRandomId().replace('-', '', 'g').replace('{', '').replace('}', '');
reason = "create";
} else {
reason = "update";
}
this._setMetaData(newContact, aContact);
debug("send: " + JSON.stringify(newContact));
request = this.createRequest();
cpmm.sendAsyncMessage("Contact:Save", {contact: newContact,
requestID: this.getRequestId(request)});
requestID: this.getRequestId({request: request, reason: reason })});
return request;
} else {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -238,7 +254,7 @@ ContactManager.prototype = {
if (this.hasPrivileges) {
request = this.createRequest();
cpmm.sendAsyncMessage("Contact:Remove", {id: aRecord.id,
requestID: this.getRequestId(request)});
requestID: this.getRequestId({request: request, reason: "remove"})});
return request;
} else {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -273,7 +289,7 @@ ContactManager.prototype = {
if (req) {
let result = this._convertContactsArray(contacts);
debug("result: " + JSON.stringify(result));
Services.DOMRequest.fireSuccess(req, result);
Services.DOMRequest.fireSuccess(req.request, result);
} else {
debug("no request stored!" + msg.requestID);
}
@ -283,7 +299,13 @@ ContactManager.prototype = {
case "Contact:Remove:Return:OK":
req = this.getRequest(msg.requestID);
if (req)
Services.DOMRequest.fireSuccess(req, null);
Services.DOMRequest.fireSuccess(req.request, null);
// Fire oncontactchange event
if (this._oncontactchange) {
let event = new MozContactEvent(msg.contactID, req.reason);
this._oncontactchange.handleEvent(event);
}
break;
case "Contacts:Find:Return:KO":
case "Contact:Save:Return:KO":
@ -291,7 +313,7 @@ ContactManager.prototype = {
case "Contacts:Clear:Return:KO":
req = this.getRequest(msg.requestID);
if (req)
Services.DOMRequest.fireError(req, msg.errorMsg);
Services.DOMRequest.fireError(req.request, msg.errorMsg);
break;
default:
debug("Wrong message: " + aMessage.name);
@ -304,7 +326,7 @@ ContactManager.prototype = {
if (this.hasPrivileges) {
request = this.createRequest();
cpmm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions,
requestID: this.getRequestId(request)});
requestID: this.getRequestId({request: request, reason: "find"})});
return request;
} else {
debug("find not allowed");
@ -316,7 +338,7 @@ ContactManager.prototype = {
let request;
if (this.hasPrivileges) {
request = this.createRequest();
cpmm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId(request)});
cpmm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId({request: request, reason: "remove"})});
return request;
} else {
debug("clear not allowed");
@ -346,6 +368,13 @@ ContactManager.prototype = {
debug("has privileges :" + this.hasPrivileges);
},
// Called from DOMRequestIpcHelper
uninit: function uninit() {
debug("uninit call");
if (this._oncontactchange)
this._oncontactchange = null;
},
classID : CONTACTMANAGER_CID,
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactManager, Ci.nsIDOMGlobalPropertyInitializer]),
@ -356,4 +385,31 @@ ContactManager.prototype = {
flags: nsIClassInfo.DOM_OBJECT})
}
// MozContactEvent object
function MozContactEvent(aContactID, aReason) {
debug("ContactEventConstr: " + aContactID + ", " + aReason);
this._contactID = aContactID;
this._reason = aReason;
}
MozContactEvent.prototype = {
get contactID() {
return this._contactID;
},
get reason() {
return this._reason;
},
classID: Components.ID("{a8cd4ba0-93d1-11e1-b0c4-0800200c9a66}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMContactEvent]),
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{a8cd4ba0-93d1-11e1-b0c4-0800200c9a66}"),
contractID: "@mozilla.org/contact-event;1",
interfaces: [Ci.mozIDOMContactEvent],
flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Contact Change Event"})
}
const NSGetFactory = XPCOMUtils.generateNSGetFactory([Contact, ContactManager, ContactProperties, ContactAddress, ContactFindOptions])

View File

@ -11,6 +11,6 @@ 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 {50a820b0-ced0-11e0-9572-0800200c9a66} ContactManager.js
contract @mozilla.org/contactManager;1 {50a820b0-ced0-11e0-9572-0800200c9a66}
component {d9ca0950-93d1-11e1-b0c4-0800200c9a66} ContactManager.js
contract @mozilla.org/contactManager;1 {d9ca0950-93d1-11e1-b0c4-0800200c9a66}
category JavaScript-navigator-property mozContacts @mozilla.org/contactManager;1

View File

@ -95,21 +95,28 @@ let DOMContactManager = {
debug("result:" + JSON.stringify(result));
ppmm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result});
}.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this),
msg.findOptions);
break;
case "Contact:Save":
this._db.saveContact(msg.contact, function() { ppmm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
this._db.saveContact(
msg.contact,
function() { ppmm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID, contactID: msg.contact.id }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
);
break;
case "Contact:Remove":
this._db.removeContact(msg.id,
function() { ppmm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
this._db.removeContact(
msg.id,
function() { ppmm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID, contactID: msg.id }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
);
break;
case "Contacts:Clear":
this._db.clear(function() { ppmm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
this._db.clear(
function() { ppmm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
);
}
}
}

View File

@ -231,6 +231,12 @@ var steps = [
ok(true, "Adding a new contact1");
createResult1 = new mozContact();
createResult1.init(properties1);
mozContacts.oncontactchange = function(event) {
is(event.contactID, createResult1.id, "Same contactID");
is(event.reason, "create", "Same reason");
}
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
@ -255,11 +261,135 @@ var steps = [
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring and update");
mozContacts.oncontactchange = function(event) {
is(event.contactID, findResult1.id, "Same contactID");
is(event.reason, "update", "Same reason");
}
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");
findResult1 = req.result[0];
findResult1.jobTitle = ["new Job"];
ok(findResult1.id == sample_id1, "Same ID");
checkContacts(createResult1, properties1);
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding a new contact");
mozContacts.oncontactchange = function(event) {
is(event.contactID, createResult2.id, "Same contactID");
is(event.reason, "create", "Same reason");
}
createResult2 = new mozContact();
createResult2.init({name: "newName"});
req = navigator.mozContacts.save(createResult2);
req.onsuccess = function () {
ok(createResult2.id, "The contact now has an ID.");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");
findResult1 = req.result[0];
checkContacts(createResult1, findResult1);
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Remove contact1");
mozContacts.oncontactchange = function(event) {
is(event.contactID, createResult1.id, "Same contactID");
is(event.reason, "remove", "Same reason");
}
req = navigator.mozContacts.remove(createResult1);
req.onsuccess = function () {
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 0, "Found no contact.");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Remove contact2");
mozContacts.oncontactchange = function(event) {
is(event.contactID, createResult2.id, "Same contactID");
is(event.reason, "remove", "Same reason");
}
req = navigator.mozContacts.remove(createResult2);
req.onsuccess = function () {
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 0, "Found no contact.");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Deleting database");
mozContacts.oncontactchange = function(event) {
is(event.contactID, "undefined", "Same contactID");
is(event.reason, "remove", "Same reason");
}
req = mozContacts.clear();
req.onsuccess = function () {
ok(true, "Deleted the database");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding a new contact with properties1");
createResult1 = new mozContact();
createResult1.init(properties1);
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
sample_id1 = createResult1.id;
checkContacts(properties1, createResult1);
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring tel1");
var options = {filterBy: ["tel"],
filterOp: "contains",
filterValue: properties1.tel[1].substring(1,5)};
mozContacts.oncontactchange = null;
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");

View File

@ -4,6 +4,7 @@
#include "domstubs.idl"
#include "nsIDOMContactProperties.idl"
#include "nsIDOMEvent.idl"
interface nsIArray;
interface nsIDOMContactFindOptions;
@ -20,7 +21,14 @@ interface nsIDOMContact : nsIDOMContactProperties
void init(in nsIDOMContactProperties properties); // Workaround BUG 723206
};
[scriptable, uuid(50a820b0-ced0-11e0-9572-0800200c9a66)]
[scriptable, uuid(a8cd4ba0-93d1-11e1-b0c4-0800200c9a66)]
interface mozIDOMContactEvent : nsIDOMEvent
{
readonly attribute DOMString contactID;
readonly attribute DOMString reason;
};
[scriptable, uuid(d9ca0950-93d1-11e1-b0c4-0800200c9a66)]
interface nsIDOMContactManager : nsISupports
{
nsIDOMDOMRequest find(in nsIDOMContactFindOptions options);
@ -30,4 +38,6 @@ interface nsIDOMContactManager : nsISupports
nsIDOMDOMRequest save(in nsIDOMContact contact);
nsIDOMDOMRequest remove(in nsIDOMContact contact);
};
attribute nsIDOMEventListener oncontactchange;
};

View File

@ -51,4 +51,4 @@ interface nsIDOMContactProperties : nsISupports
attribute jsval anniversary; // Date
attribute jsval sex; // DOMString
attribute jsval genderIdentity; // DOMString
};
};