[Pkg-mozext-commits] [gcontactsync] 02/11: Issue #1: Synchronize in a worker thread
David Prévot
taffit at moszumanska.debian.org
Tue Mar 24 22:41:22 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository gcontactsync.
commit 1481be9b5d7e38b467a85630c8f473bd7fd121ff
Author: Josh Geenen <joshgeenen at gmail.com>
Date: Thu Dec 25 21:06:43 2014 -0600
Issue #1: Synchronize in a worker thread
---
src/content/Sync.js | 234 ++++++++++++++++------------------------------
src/content/SyncWorker.js | 196 ++++++++++++++++++++++++++++++++++++++
2 files changed, 274 insertions(+), 156 deletions(-)
diff --git a/src/content/Sync.js b/src/content/Sync.js
index 109363b..c0bcd61 100644
--- a/src/content/Sync.js
+++ b/src/content/Sync.js
@@ -447,24 +447,26 @@ com.gContactSync.Sync = {
com.gContactSync.Sync.mContactsToUpdate = [];
var gContact,
// get the strings outside of the loop so they are only found once
- found = " * Found a match, last modified:",
- bothChanged = " * Conflict detected: the contact has been updated in " +
- "both Google and Thunderbird",
- bothGoogle = " - The Google contact will be updated",
- bothTB = " - The Thunderbird contact will be updated",
- gContacts = {};
- // Step 1: get all contacts from Google into GContact objects in an object
+ gContacts = {},
+ gContactInfo = {},
+ abCardInfo = [];
+
+ // Get all contacts from Google into GContact objects in an object
// keyed by ID.
for (var i = 0, length = googleContacts.length; i < length; i++) {
gContact = new com.gContactSync.GContact(googleContacts[i]);
gContact.lastModified = gContact.getLastModifiedDate();
gContact.id = gContact.getID(true);
gContacts[gContact.id] = gContact;
+ gContactInfo[gContact.id] = {name: gContact.getName(), lastModified: gContact.lastModified};
+ }
+ for (i = 0, length = abCards.length; i < length; ++i) {
+ abCardInfo.push({id: abCards[i].getID(), name: abCards[i].getName(), lastModified: abCards[i].getValue("LastModifiedDate")});
}
// re-initialize the contact converter (in case a pref changed)
com.gContactSync.ContactConverter.init();
- // Step 1.5: If this is the first sync then iterate through TB contacts
+ // If this is the first sync then iterate through TB contacts
// If the contact matches a Google contact then set the TB contact's
// GoogleID to its matching contact and LastModifiedDate to 0.
// This prevents some duplicates on the first sync by basically overwritting
@@ -477,7 +479,7 @@ com.gContactSync.Sync = {
// If this address book was previously synchronized with gContactSync there's no need to merge.
// The contacts will conflict and the updateGoogleInConflicts pref will be used to resolve.
- if (abCards[i].getValue("GoogleID")) continue;
+ if (abCards[i].getValue("GoogleID")) {continue;}
for (var id in gContacts) {
if (gContacts[id] && abCards[i] &&
@@ -513,162 +515,80 @@ com.gContactSync.Sync = {
com.gContactSync.Overlay.setStatusBarText(com.gContactSync.StringBundle.getStr("syncing"));
- // Step 2: iterate through TB Contacts and check for matches
- for (i = 0, length = abCards.length; i < length; i++) {
- var tbContact = abCards[i],
- id = tbContact.getID(),
- tbCardDate = tbContact.getValue("LastModifiedDate");
- com.gContactSync.LOGGER.LOG(tbContact.getName() + ": " + id);
- tbContact.id = id;
- // no ID = new contact
- if (!id) {
- if (ab.mPrefs.readOnly === "true") {
- com.gContactSync.LOGGER.LOG(" * The contact is new. " +
- "Ignoring since read-only mode is on.");
- this.mCurrentSummary.mLocal.mIgnored++;
- }
- else {
- // this.mCurrentSummary.mRemote.mAdded++; This is done after the contact is
- // successfully added
- com.gContactSync.LOGGER.LOG(" * This contact is new and will be added to Google.");
- this.mCurrentSummary.mRemote.mAdded++;
- com.gContactSync.Sync.mContactsToAdd.push(tbContact);
+ var worker = new Worker("chrome://gcontactsync/content/SyncWorker.js");
+ var workerData = {
+ mABCards: abCardInfo,
+ mGContacts: gContactInfo,
+ mLastSync: lastSync,
+ mReadOnly: ab.mPrefs.readOnly === "true",
+ mWriteOnly: ab.mPrefs.writeOnly === "true",
+ mUpdateGoogleInConflicts: ab.mPrefs.updateGoogleInConflicts === "true",
+ mCurrentSummary: this.mCurrentSummary,
+ };
+
+ // Make this == Sync when receiving messages from the worker
+ var self = this;
+ worker.onmessage = function(event) {
+ self.onworkermessage.call(self, event);
+ };
+
+ this.onworkermessage = function syncWorkerOnMessage(event) {
+ if (event.data.mType === "log") {
+ com.gContactSync.LOGGER.LOG(event.data.mMessage);
+ } else if (event.data.mType === "newTBContact") {
+ var newCard = ab.newContact();
+ com.gContactSync.ContactConverter.makeCard(gContacts[event.data.mID], newCard);
+ } else if (event.data.mType === "updateTBCard") {
+ var tbContact = abCards[event.data.mTBCardIndex];
+ com.gContactSync.ContactConverter.makeCard(gContacts[tbContact.getID()], tbContact);
+ } else if (event.data.mType === "done") {
+
+ for (var i in event.data.mCurrentSummary) {
+ if (event.data.mCurrentSummary.hasOwnProperty(i)) {this.mCurrentSummary[i] = event.data.mCurrentSummary[i];}
}
- }
- // if there is a matching Google Contact
- else if (gContacts[id]) {
- gContact = gContacts[id];
- // remove it from gContacts
- gContacts[id] = null;
- // note that this returns 0 if readOnly is set
- gCardDate = ab.mPrefs.writeOnly !== "true" ? gContact.lastModified : 0; // TODO - should this be a 1?
- // 4 options
- // if both were updated
- com.gContactSync.LOGGER.LOG(found +
- "\n - Google: " + gCardDate +
- " (" + new Date(gCardDate) + ")" +
- "\n - Thunderbird: " + (tbCardDate * 1000) +
- " (" + new Date(tbCardDate * 1000) + ")");
- com.gContactSync.LOGGER.VERBOSE_LOG(" * Google ID: " + id);
- // If there is a conflict, looks at the updateGoogleInConflicts
- // preference and updates Google if it's true, or Thunderbird if false
- if (gCardDate > lastSync && tbCardDate > lastSync / 1000) {
- com.gContactSync.LOGGER.LOG(bothChanged);
- this.mCurrentSummary.mConflicted++;
- if (ab.mPrefs.writeOnly === "true" || ab.mPrefs.updateGoogleInConflicts === "true") {
- com.gContactSync.LOGGER.LOG(bothGoogle);
- var toUpdate = {};
- toUpdate.gContact = gContact;
- toUpdate.abCard = tbContact;
- this.mCurrentSummary.mRemote.mUpdated++;
- com.gContactSync.Sync.mContactsToUpdate.push(toUpdate);
- }
- // update Thunderbird if writeOnly is off and updateGoogle is off
- else {
- com.gContactSync.LOGGER.LOG(bothTB);
- this.mCurrentSummary.mLocal.mUpdated++;
- com.gContactSync.ContactConverter.makeCard(gContact, tbContact);
- }
+ for (i = 0, length = event.data.mContactsToAdd.length; i < length; ++i) {
+ this.mContactsToAdd.push(abCards[event.data.mContactsToAdd[i]]);
}
- // if the contact from Google is newer update the TB card
- else if (gCardDate > lastSync) {
- com.gContactSync.LOGGER.LOG(" * The contact from Google is newer...Updating the" +
- " contact from Thunderbird");
- this.mCurrentSummary.mLocal.mUpdated++;
- com.gContactSync.ContactConverter.makeCard(gContact, tbContact);
+ for (i = 0, length = event.data.mContactsToUpdate.length; i < length; ++i) {
+ var abCard = abCards[event.data.mContactsToUpdate[i]];
+ this.mContactsToUpdate.push({abCard: abCard, gContact: gContacts[abCard.getID()]});
}
- // if the TB card is newer update Google
- else if (tbCardDate > lastSync / 1000) {
- com.gContactSync.LOGGER.LOG(" * The contact from Thunderbird is newer...Updating the" +
- " contact from Google");
- var toUpdate = {};
- toUpdate.gContact = gContact;
- toUpdate.abCard = tbContact;
- this.mCurrentSummary.mRemote.mUpdated++;
- com.gContactSync.Sync.mContactsToUpdate.push(toUpdate);
+ for (i = 0, length = event.data.mContactsToDelete.length; i < length; ++i) {
+ this.mContactsToDelete.push(gContacts[event.data.mContactsToDelete[i]]);
}
- // otherwise nothing needs to be done
- else {
- com.gContactSync.LOGGER.LOG(" * Neither contact has changed");
- this.mCurrentSummary.mNotChanged++;
+ for (i = 0, length = event.data.mCardsToDelete.length; i < length; ++i) {
+ cardsToDelete.push(abCards[event.data.mCardsToDelete[i]]);
}
- }
- // if there isn't a match, but the card is new, add it to Google
- else if (tbContact.getValue("LastModifiedDate") > lastSync / 1000 ||
- isNaN(lastSync)) {
- com.gContactSync.LOGGER.LOG(" * Contact is new, adding to Google.");
- this.mCurrentSummary.mRemote.mAdded++;
- com.gContactSync.Sync.mContactsToAdd.push(tbContact);
- }
- // Otherwise, delete the contact from the address book if writeOnly
- // mode isn't on
- else if (ab.mPrefs.writeOnly !== "true") {
- com.gContactSync.LOGGER.LOG(" * Contact deleted from Google, " +
- "deleting local copy");
- this.mCurrentSummary.mLocal.mRemoved++;
- cardsToDelete.push(tbContact);
- } else {
- this.mCurrentSummary.mRemote.mIgnored++;
- com.gContactSync.LOGGER.LOG(" * Contact deleted from Google, ignoring" +
- " since write-only mode is enabled");
- }
- }
- // STEP 3: Check for old Google contacts to delete and new contacts to add to TB
- com.gContactSync.LOGGER.LOG("**Looking for unmatched Google contacts**");
- for (var id in gContacts) {
- var gContact = gContacts[id];
- if (gContact) {
-
- // If writeOnly is on, then set the last modified date to 1 so TB grabs
- // all the contacts from Google during the first sync.
- var gCardDate = ab.mPrefs.writeOnly != "true" ? gContact.lastModified : 1;
- com.gContactSync.LOGGER.LOG(gContact.getName() + " - " + gCardDate +
- "\n" + id);
- if (gCardDate > lastSync || isNaN(lastSync)) {
- com.gContactSync.LOGGER.LOG(" * The contact is new and will be added to Thunderbird");
- this.mCurrentSummary.mLocal.mAdded++;
- var newCard = ab.newContact();
- com.gContactSync.ContactConverter.makeCard(gContact, newCard);
- }
- else if (ab.mPrefs.readOnly != "true") {
- com.gContactSync.LOGGER.LOG(" * The contact is old and will be deleted");
- this.mCurrentSummary.mLocal.mRemoved++;
- com.gContactSync.Sync.mContactsToDelete.push(gContact);
+ var threshold = com.gContactSync.Preferences.mSyncPrefs
+ .confirmDeleteThreshold.value;
+ // Request permission from the user to delete > threshold contacts from a
+ // single source
+ // If the user clicks Cancel the AB is disabled
+ if (threshold > -1 &&
+ (cardsToDelete.length >= threshold ||
+ com.gContactSync.Sync.mContactsToDelete.length >= threshold) &&
+ !com.gContactSync.Sync.requestDeletePermission(cardsToDelete.length,
+ com.gContactSync.Sync.mContactsToDelete.length)) {
+ // If canceled here then reset most remote counts and local deleted to 0
+ this.mCurrentSummary.mLocal.mRemoved = 0;
+ this.mCurrentSummary.mRemote.mAdded = 0;
+ this.mCurrentSummary.mRemote.mRemoved = 0;
+ this.mCurrentSummary.mRemote.mUpdated = 0;
+ com.gContactSync.Sync.syncNextUser();
+ return;
}
- else {
- com.gContactSync.LOGGER.LOG (" * The contact was deleted in Thunderbird. " +
- "Ignoring since read-only mode is on.");
- this.mCurrentSummary.mLocal.mIgnored++;
+ // delete the old contacts from Thunderbird
+ if (cardsToDelete.length > 0) {
+ ab.deleteContacts(cardsToDelete);
}
- }
- }
- var threshold = com.gContactSync.Preferences.mSyncPrefs
- .confirmDeleteThreshold.value;
- // Request permission from the user to delete > threshold contacts from a
- // single source
- // If the user clicks Cancel the AB is disabled
- if (threshold > -1 &&
- (cardsToDelete.length >= threshold ||
- com.gContactSync.Sync.mContactsToDelete.length >= threshold) &&
- !com.gContactSync.Sync.requestDeletePermission(cardsToDelete.length,
- com.gContactSync.Sync.mContactsToDelete.length)) {
- // If canceled here then reset most remote counts and local deleted to 0
- this.mCurrentSummary.mLocal.mRemoved = 0;
- this.mCurrentSummary.mRemote.mAdded = 0;
- this.mCurrentSummary.mRemote.mRemoved = 0;
- this.mCurrentSummary.mRemote.mUpdated = 0;
- com.gContactSync.Sync.syncNextUser();
- return;
- }
- // delete the old contacts from Thunderbird
- if (cardsToDelete.length > 0) {
- ab.deleteContacts(cardsToDelete);
- }
- com.gContactSync.LOGGER.LOG("***Deleting contacts from Google***");
- // delete contacts from Google
- com.gContactSync.Sync.processDeleteQueue();
+ com.gContactSync.LOGGER.LOG("***Deleting contacts from Google***");
+ // delete contacts from Google
+ com.gContactSync.Sync.processDeleteQueue();
+ }
+ };
+ worker.postMessage(workerData);
},
/**
* Shows a confirmation dialog asking the user to give gContactSync permission
@@ -688,12 +608,14 @@ com.gContactSync.Sync = {
com.gContactSync.LOGGER.LOG("Requesting permission to delete " +
"TB: " + aNumTB + ", Google: " + aNumGoogle +
" contacts...");
+
if (!com.gContactSync.confirm(warning)) {
com.gContactSync.LOGGER.LOG(" * Permission denied, disabling AB");
com.gContactSync.Sync.mCurrentAb.savePref("Disabled", true);
com.gContactSync.alert(com.gContactSync.StringBundle.getStr("deleteCancel"));
return false;
}
+
com.gContactSync.LOGGER.LOG(" * Permission granted");
return true;
},
diff --git a/src/content/SyncWorker.js b/src/content/SyncWorker.js
new file mode 100644
index 0000000..50629af
--- /dev/null
+++ b/src/content/SyncWorker.js
@@ -0,0 +1,196 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is gContactSync.
+ *
+ * The Initial Developer of the Original Code is
+ * Josh Geenen <gcontactsync at pirules.org>.
+ * Portions created by the Initial Developer are Copyright (C) 2014
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * A worker for synchronizing contacts. Calls postMessage to send data back to the main thread.
+ *
+ * @param aData {object} The sync data.
+ */
+function SyncWorker(aData) {
+
+ var found = " * Found a match, last modified:",
+ bothChanged = " * Conflict detected: the contact has been updated in " +
+ "both Google and Thunderbird",
+ bothGoogle = " - The Google contact will be updated",
+ bothTB = " - The Thunderbird contact will be updated";
+
+ var cardsToDelete = [],
+ contactsToDelete = [],
+ contactsToUpdate = [],
+ contactsToAdd = [];
+
+ // Iterate through TB Contacts and check for matches
+ for (var i = 0, length = aData.mABCards.length; i < length; i++) {
+ var tbContact = aData.mABCards[i];
+ log(tbContact.name + ": " + tbContact.id);
+ // no ID = new contact
+ if (!tbContact.id) {
+ if (aData.mReadOnly) {
+ log(" * The contact is new. Ignoring since read-only mode is on.");
+ aData.mCurrentSummary.mLocal.mIgnored++;
+ }
+ else {
+ log(" * This contact is new and will be added to Google.");
+ aData.mCurrentSummary.mRemote.mAdded++;
+ contactsToAdd.push(i);
+ }
+ }
+ // if there is a matching Google Contact
+ else if (aData.mGContacts[tbContact.id]) {
+ gContact = aData.mGContacts[tbContact.id];
+ // remove it from aData.mGContacts
+ aData.mGContacts[tbContact.id] = null;
+ gCardDate = aData.mReadOnly ? 0 : gContact.lastModified; // TODO - should this be a 1?
+ // 4 options
+ // if both were updated
+ log(found +
+ "\n - Google: " + gCardDate +
+ " (" + new Date(gCardDate) + ")" +
+ "\n - Thunderbird: " + (tbContact.lastModified * 1000) +
+ " (" + new Date(tbContact.lastModified * 1000) + ")");
+ // If there is a conflict, looks at the updateGoogleInConflicts
+ // preference and updates Google if it's true, or Thunderbird if false
+ if (gCardDate > aData.mLastSync && tbContact.lastModified > aData.mLastSync / 1000) {
+ log(bothChanged);
+ aData.mCurrentSummary.mConflicted++;
+ if (aData.mWriteOnly || aData.mUpdateGoogleInConflicts) {
+ log(bothGoogle);
+ aData.mCurrentSummary.mRemote.mUpdated++;
+ contactsToUpdate.push(i);
+ }
+ // update Thunderbird if writeOnly is off and updateGoogle is off
+ else {
+ log(bothTB);
+ aData.mCurrentSummary.mLocal.mUpdated++;
+ postMessage({mType: "updateTBCard", mTBCardIndex: i});
+ }
+ }
+ // if the contact from Google is newer update the TB card
+ else if (gCardDate > aData.mLastSync) {
+ log(" * The contact from Google is newer...Updating the contact from Thunderbird");
+ aData.mCurrentSummary.mLocal.mUpdated++;
+ postMessage({mType: "updateTBCard", mTBCardIndex: i});
+ }
+ // if the TB card is newer update Google
+ else if (tbContact.lastModified > aData.mLastSync / 1000) {
+ log(" * The contact from Thunderbird is newer...Updating the contact from Google");
+ aData.mCurrentSummary.mRemote.mUpdated++;
+ contactsToUpdate.push(i);
+ }
+ // otherwise nothing needs to be done
+ else {
+ log(" * Neither contact has changed");
+ aData.mCurrentSummary.mNotChanged++;
+ }
+ }
+ // if there isn't a match, but the card is new, add it to Google
+ else if (tbContact.lastModified > aData.mLastSync / 1000 ||
+ isNaN(aData.mLastSync)) {
+ log(" * Contact is new, adding to Google.");
+ aData.mCurrentSummary.mRemote.mAdded++;
+ contactsToAdd.push(i);
+ }
+ // Otherwise, delete the contact from the address book if writeOnly
+ // mode isn't on
+ else if (!aData.mWriteOnly) {
+ log(" * Contact deleted from Google, deleting local copy");
+ aData.mCurrentSummary.mLocal.mRemoved++;
+ cardsToDelete.push(i);
+ } else {
+ aData.mCurrentSummary.mRemote.mIgnored++;
+ log(" * Contact deleted from Google, ignoring since write-only mode is enabled");
+ }
+ }
+
+ // Check for old Google contacts to delete and new contacts to add to TB
+ log("**Looking for unmatched Google contacts**");
+ for (var id in aData.mGContacts) {
+ var gContact = aData.mGContacts[id];
+ if (gContact) {
+
+ // If writeOnly is on, then set the last modified date to 1 so TB grabs
+ // all the contacts from Google during the first sync.
+ var gCardDate = aData.mWriteOnly ? 1 : gContact.lastModified;
+ log(gContact.name + " - " + gCardDate + "\n" + id);
+ if (gCardDate > aData.mLastSync || isNaN(aData.mLastSync)) {
+ log(" * The contact is new and will be added to Thunderbird");
+ postMessage({mType: "newTBContact", mID: id});
+ aData.mCurrentSummary.mLocal.mAdded++;
+ }
+ else if (!aData.mReadOnly) {
+ log(" * The contact is old and will be deleted");
+ aData.mCurrentSummary.mLocal.mRemoved++;
+ contactsToDelete.push(id);
+ }
+ else {
+ log (" * The contact was deleted in Thunderbird. " +
+ "Ignoring since read-only mode is on.");
+ aData.mCurrentSummary.mLocal.mIgnored++;
+ }
+ }
+ }
+
+ postMessage({mType: "done",
+ mCurrentSummary: aData.mCurrentSummary,
+ mContactsToAdd: contactsToAdd,
+ mContactsToDelete: contactsToDelete,
+ mContactsToUpdate: contactsToUpdate,
+ mCardsToDelete: cardsToDelete});
+}
+
+/**
+ * Logs the given message.
+ *
+ * @param aMessage {string} The message.
+ */
+function log(aMessage) {
+ postMessage({
+ mType: "log",
+ mMessage: aMessage
+ });
+}
+
+/**
+ * Called on messages sent to this worker. Calls SyncWorker if the event contains data.
+ *
+ * @param event {event} The event.
+ */
+onmessage = function(event) {
+ if (event.data) {
+ SyncWorker(event.data);
+ }
+};
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/gcontactsync.git
More information about the Pkg-mozext-commits
mailing list