[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