Bug 864556 - Expose database revision in Contacts API. r=gwagner sr=mounir

--HG--
extra : rebase_source : b36e856f9fd85155096f88cb0c8ad41038052a25
This commit is contained in:
Reuben Morais 2013-04-25 10:15:47 -07:00
parent dafd5e8751
commit 376fc8de8a
6 changed files with 111 additions and 20 deletions

View File

@ -381,7 +381,7 @@ Contact.prototype = {
// ContactManager
const CONTACTMANAGER_CONTRACTID = "@mozilla.org/contactManager;1";
const CONTACTMANAGER_CID = Components.ID("{4efae3f8-dd69-4622-97c8-f16e4d38d95c}");
const CONTACTMANAGER_CID = Components.ID("{7bfb6481-f946-4254-afc5-d7fe9f5c45a3}");
const nsIDOMContactManager = Components.interfaces.nsIDOMContactManager;
function ContactManager()
@ -545,6 +545,13 @@ ContactManager.prototype = {
this._oncontactchange.handleEvent(event);
}
break;
case "Contacts:Revision":
if (DEBUG) debug("new revision: " + msg.revision);
req = this.getRequest(msg.requestID);
if (req) {
Services.DOMRequest.fireSuccess(req, msg.revision);
}
break;
default:
if (DEBUG) debug("Wrong message: " + aMessage.name);
}
@ -565,6 +572,7 @@ ContactManager.prototype = {
case "find":
case "getSimContacts":
case "listen":
case "revision":
access = "read";
break;
default:
@ -754,6 +762,23 @@ ContactManager.prototype = {
return request;
},
getRevision: function() {
let request = this.createRequest();
let allowCallback = function() {
cpmm.sendAsyncMessage("Contacts:GetRevision", {
requestID: this.getRequestId(request)
});
}.bind(this);
let cancelCallback = function() {
Services.DOMRequest.fireError(request);
};
this.askPermission("revision", request, allowCallback, cancelCallback);
return request;
},
init: function(aWindow) {
this.initHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
"Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
@ -763,7 +788,8 @@ ContactManager.prototype = {
"Contacts:GetSimContacts:Return:KO",
"Contact:Changed",
"PermissionPromptHelper:AskPermission:OK",
"Contacts:GetAll:Next"]);
"Contacts:GetAll:Next",
"Contacts:Revision"]);
},
// Called from DOMRequestIpcHelper

View File

@ -20,6 +20,6 @@ component {72a5ee28-81d8-4af8-90b3-ae935396cc66} ContactManager.js
contract @mozilla.org/contact;1 {72a5ee28-81d8-4af8-90b3-ae935396cc66}
category JavaScript-global-constructor-maybe dom.mozContacts.enabled mozContact,@mozilla.org/contact;1
component {4efae3f8-dd69-4622-97c8-f16e4d38d95c} ContactManager.js
contract @mozilla.org/contactManager;1 {4efae3f8-dd69-4622-97c8-f16e4d38d95c}
component {7bfb6481-f946-4254-afc5-d7fe9f5c45a3} ContactManager.js
contract @mozilla.org/contactManager;1 {7bfb6481-f946-4254-afc5-d7fe9f5c45a3}
category JavaScript-navigator-property-maybe dom.mozContacts.enabled mozContacts,@mozilla.org/contactManager;1

View File

@ -19,11 +19,13 @@ Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
Cu.import("resource://gre/modules/Timer.jsm");
const DB_NAME = "contacts";
const DB_VERSION = 10;
const DB_VERSION = 11;
const STORE_NAME = "contacts";
const SAVED_GETALL_STORE_NAME = "getallcache";
const CHUNK_SIZE = 20;
const CHUNK_INTERVAL = 500;
const REVISION_STORE = "revision";
const REVISION_KEY = "revision";
function ContactDispatcher(aContacts, aFullContacts, aCallback, aNewTxn, aClearDispatcher) {
let nextIndex = 0;
@ -362,6 +364,14 @@ ContactDB.prototype = {
cursor.continue();
}
};
} else if (currVersion == 10) {
if (DEBUG) debug("Adding object store for database revision");
db.createObjectStore(REVISION_STORE).put(0, REVISION_KEY);
}
// Increment the DB revision on future schema changes as well
if (currVersion > 10) {
this.incrementRevision(aTransaction);
}
}
@ -595,7 +605,14 @@ ContactDB.prototype = {
});
},
saveContact: function saveContact(aContact, successCb, errorCb) {
incrementRevision: function CDB_incrementRevision(txn) {
let revStore = txn.objectStore(REVISION_STORE);
revStore.get(REVISION_KEY).onsuccess = function(e) {
revStore.put(parseInt(e.target.result, 10) + 1, REVISION_KEY);
};
},
saveContact: function CDB_saveContact(aContact, successCb, errorCb) {
let contact = this.makeImport(aContact);
this.newTxn("readwrite", STORE_NAME, function (txn, store) {
if (DEBUG) debug("Going to update" + JSON.stringify(contact));
@ -623,6 +640,8 @@ ContactDB.prototype = {
}
this.invalidateCache();
}.bind(this);
this.incrementRevision(txn);
}.bind(this), successCb, errorCb);
},
@ -633,7 +652,8 @@ ContactDB.prototype = {
store.delete(aId).onsuccess = function() {
aSuccessCb();
};
}, null, aErrorCb);
this.incrementRevision(txn);
}.bind(this), null, aErrorCb);
}.bind(this));
},
@ -641,7 +661,8 @@ ContactDB.prototype = {
this.newTxn("readwrite", STORE_NAME, function (txn, store) {
if (DEBUG) debug("Going to clear all!");
store.clear();
}, aSuccessCb, aErrorCb);
this.incrementRevision(txn);
}.bind(this), aSuccessCb, aErrorCb);
},
createCacheForQuery: function CDB_createCacheForQuery(aQuery, aSuccessCb, aFailureCb) {
@ -721,6 +742,15 @@ ContactDB.prototype = {
}.bind(this));
},
getRevision: function CDB_getRevision(aSuccessCb) {
if (DEBUG) debug("getRevision");
this.newTxn("readonly", REVISION_STORE, function (txn, store) {
store.get(REVISION_KEY).onsuccess = function (e) {
aSuccessCb(e.target.result);
}
});
},
/*
* 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
@ -881,6 +911,6 @@ ContactDB.prototype = {
},
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, SAVED_GETALL_STORE_NAME, REVISION_STORE], aGlobal);
}
};

View File

@ -42,7 +42,8 @@ let ContactService = {
this._messages = ["Contacts:Find", "Contacts:GetAll", "Contacts:GetAll:SendNow",
"Contacts:Clear", "Contact:Save",
"Contact:Remove", "Contacts:GetSimContacts",
"Contacts:RegisterForMessages", "child-process-shutdown"];
"Contacts:RegisterForMessages", "child-process-shutdown",
"Contacts:GetRevision"];
this._children = [];
this._messages.forEach(function(msgName) {
ppmm.addMessageListener(msgName, this);
@ -190,6 +191,19 @@ let ContactService = {
}
}.bind(this));
break;
case "Contacts:GetRevision":
if (!this.assertPermission(aMessage, "contacts-read")) {
return null;
}
this._db.getRevision(
function(revision) {
mm.sendAsyncMessage("Contacts:Revision", {
requestID: msg.requestID,
revision: revision
});
}
);
break;
case "Contacts:RegisterForMessages":
if (!aMessage.target.assertPermission("contacts-read")) {
return null;

View File

@ -246,25 +246,44 @@ function tests() {
var req;
var index = 0;
var initialRev;
function checkRevision(revision, msg, then) {
var revReq = mozContacts.getRevision();
revReq.onsuccess = function(e) {
is(e.target.result, initialRev+revision, msg);
then();
};
revReq.onerror = onFailure;
}
var mozContacts = window.navigator.mozContacts;
ok(mozContacts, "mozContacts exists");
ok("mozContact" in window, "mozContact exists");
var steps = [
function () {
ok(true, "Deleting database");
req = mozContacts.clear();
req.onsuccess = function () {
ok(true, "Deleted the database");
function() {
mozContacts.getRevision().onsuccess = function(e) {
initialRev = e.target.result;
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Deleting database");
checkRevision(0, "Initial revision is 0", function() {
req = mozContacts.clear();
req.onsuccess = function () {
ok(true, "Deleted the database");
checkRevision(1, "Revision was incremented on clear", next);
};
req.onerror = onFailure;
});
},
function () {
ok(true, "Retrieving all contacts");
req = mozContacts.find({});
req.onsuccess = function () {
is(req.result.length, 0, "Empty database.");
next();
checkRevision(1, "Revision was not incremented on find", next);
};
req.onerror = onFailure;
},
@ -276,7 +295,7 @@ var steps = [
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
sample_id1 = createResult1.id;
next();
checkRevision(2, "Revision was incremented on save", next);
};
req.onerror = onFailure;
},
@ -298,7 +317,7 @@ var steps = [
req2.onsuccess = function () {
is(req2.result.length, 0, "Empty Database.");
clearTemps();
next();
checkRevision(3, "Revision was incremented on remove", next);
}
req2.onerror = onFailure;
}

View File

@ -20,7 +20,7 @@ interface nsIDOMContact : nsIContactProperties
void init(in nsIContactProperties properties); // Workaround BUG 723206
};
[scriptable, uuid(4efae3f8-dd69-4622-97c8-f16e4d38d95c)]
[scriptable, uuid(7bfb6481-f946-4254-afc5-d7fe9f5c45a3)]
interface nsIDOMContactManager : nsISupports
{
nsIDOMDOMRequest find(in nsIContactFindOptions options);
@ -36,4 +36,6 @@ interface nsIDOMContactManager : nsISupports
nsIDOMDOMRequest getSimContacts(in DOMString type);
attribute nsIDOMEventListener oncontactchange;
nsIDOMDOMRequest getRevision();
};