[Pkg-mozext-commits] [gcontactsync] 04/11: Issue #63: Throttle setPhoto requests
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 ae9195173dde99ead555345bd7e45062eb9d175f
Author: Josh Geenen <joshgeenen at gmail.com>
Date: Sun Mar 22 13:59:08 2015 -0500
Issue #63: Throttle setPhoto requests
---
src/content/GContact.js | 99 +++++++++++++++---------------
src/content/Sync.js | 101 +++++++++++++++++++++----------
src/locale/en-US/gcontactsync.properties | 1 +
3 files changed, 119 insertions(+), 82 deletions(-)
diff --git a/src/content/GContact.js b/src/content/GContact.js
index c43f794..63e2ef6 100644
--- a/src/content/GContact.js
+++ b/src/content/GContact.js
@@ -802,24 +802,25 @@ com.gContactSync.GContact.prototype = {
return val.substr(val.lastIndexOf("/") + 1);
},
/**
- * Sets the photo for this contact. Note that this may not immediately take
+ * Sets the photo for this contact. Note that this will not immediately take
* effect as contacts must be added to Google and then retrieved before a
- * photo can be added.
+ * photo can be added, and Google throttles requests.
*
* @param aURI {string|nsIURI} A string with the URI of a contact photo.
*/
setPhoto: function GContact_setPhoto(aURI) {
com.gContactSync.LOGGER.VERBOSE_LOG("Entering GContact.setPhoto:");
- var photoInfo = this.getPhotoInfo();
// If the URI is empty or a chrome URL remove the photo, if present
// TODO - this should probably just check if it is the default photo
if (!aURI) {
+ var photoInfo = this.getPhotoInfo();
// Easy case: URI is empty and this contact doesn't have a photo
if (!photoInfo || !(photoInfo.etag)) {
com.gContactSync.LOGGER.VERBOSE_LOG(" * URI is empty, contact has no photo");
return;
}
com.gContactSync.LOGGER.VERBOSE_LOG(" * URI is empty, photo will be removed");
+ // TODO - this needs to be queued
// Remove the photo
var httpReq = new com.gContactSync.GHttpRequest("delete",
com.gContactSync.Sync.mCurrentAuthToken,
@@ -837,54 +838,54 @@ com.gContactSync.GContact.prototype = {
httpReq.mOn503 = com.gContactSync.Sync.m503Function;
httpReq.addHeaderItem("If-Match", "*");
httpReq.send();
+ } else {
+ // The URI exists, so update or add the photo
+ // NOTE: A photo cannot be added until the contact has been added
+ com.gContactSync.LOGGER.VERBOSE_LOG(" * Photo will be uploaded");
+ this.mNewPhotoURI = aURI;
+ }
+ },
+ /**
+ * Uploads the photo at the given URI.
+ *
+ * @param aURI {string|nsIURI} A string with the URI of a contact photo.
+ */
+ uploadPhoto: function GContact_uploadPhoto(aURI) {
+ var photoInfo = this.getPhotoInfo();
+ // Send the PUT request
+ // TODO - this really needs error handling...
+ var ios = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService),
+ outChannel = ios.newChannel(photoInfo.url, null, null),
+ inChannel = aURI instanceof Components.interfaces.nsIURI ?
+ ios.newChannelFromURI(aURI) :
+ ios.newChannel(aURI, null, null);
+ outChannel = outChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
+ // Set the upload data
+ outChannel = outChannel.QueryInterface(Components.interfaces.nsIUploadChannel);
+ // Set the input stream as the photo URI
+ // See https://www.mozdev.org/bugs/show_bug.cgi?id=22757 for the try/catch
+ // block, I didn't see a way to tell if the item pointed to by aURI exists
+ try {
+ outChannel.setUploadStream(inChannel.open(), photoInfo.type, -1);
+ }
+ catch (e) {
+ com.gContactSync.LOGGER.LOG_WARNING("The photo at '" + aURI + "' doesn't exist", e);
return;
}
- // The URI exists, so update or add the photo
- // NOTE: A photo cannot be added until the contact has been added
- else {
- // If this is a new contact then nothing can be done until the contact is
- // added to Google
- if (this.mIsNew || !photoInfo) {
- com.gContactSync.LOGGER.VERBOSE_LOG(" * Photo will be added after the contact is created");
- this.mNewPhotoURI = aURI;
- return;
- }
- com.gContactSync.LOGGER.VERBOSE_LOG(" * Photo will be updated");
- // Otherwise send the PUT request
- // TODO - this really needs error handling...
- var ios = Components.classes["@mozilla.org/network/io-service;1"]
- .getService(Components.interfaces.nsIIOService),
- outChannel = ios.newChannel(photoInfo.url, null, null),
- inChannel = aURI instanceof Components.interfaces.nsIURI ?
- ios.newChannelFromURI(aURI) :
- ios.newChannel(aURI, null, null);
- outChannel = outChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
- // Set the upload data
- outChannel = outChannel.QueryInterface(Components.interfaces.nsIUploadChannel);
- // Set the input stream as the photo URI
- // See https://www.mozdev.org/bugs/show_bug.cgi?id=22757 for the try/catch
- // block, I didn't see a way to tell if the item pointed to by aURI exists
- try {
- outChannel.setUploadStream(inChannel.open(), photoInfo.type, -1);
- }
- catch (e) {
- com.gContactSync.LOGGER.LOG_WARNING("The photo at '" + aURI + "' doesn't exist", e);
- return;
- }
- // set the request type to PUT (this has to be after setting the upload data)
- outChannel = outChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
- outChannel.requestMethod = "PUT";
- // Setup the header: Authorization and Content-Type: image/*
- outChannel.setRequestHeader("Authorization", com.gContactSync.Sync.mCurrentAuthToken, false);
- outChannel.setRequestHeader("Content-Type", photoInfo.type, false);
- outChannel.setRequestHeader("If-Match", "*", false);
- outChannel.open();
- try {
- com.gContactSync.LOGGER.VERBOSE_LOG(" * Update status: " + outChannel.responseStatus);
- }
- catch (e) {
- com.gContactSync.LOGGER.LOG_WARNING(" * outChannel.responseStatus failed", e);
- }
+ // set the request type to PUT (this has to be after setting the upload data)
+ outChannel = outChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
+ outChannel.requestMethod = "PUT";
+ // Setup the header: Authorization and Content-Type: image/*
+ outChannel.setRequestHeader("Authorization", com.gContactSync.Sync.mCurrentAuthToken, false);
+ outChannel.setRequestHeader("Content-Type", photoInfo.type, false);
+ outChannel.setRequestHeader("If-Match", "*", false);
+ outChannel.open();
+ try {
+ com.gContactSync.LOGGER.VERBOSE_LOG(" * Update status: " + outChannel.responseStatus);
+ }
+ catch (e) {
+ com.gContactSync.LOGGER.LOG_WARNING(" * outChannel.responseStatus failed", e);
}
},
/**
diff --git a/src/content/Sync.js b/src/content/Sync.js
index c0bcd61..00f75a4 100644
--- a/src/content/Sync.js
+++ b/src/content/Sync.js
@@ -47,6 +47,8 @@ com.gContactSync.Sync = {
mContactsToDelete: [],
/** New contacts to add to Google */
mContactsToAdd: [],
+ /** Contacts whose photos need to be written */
+ mContactsToUploadPhoto: [],
/** Contacts to update */
mContactsToUpdate: [],
/** Groups to delete */
@@ -442,12 +444,12 @@ com.gContactSync.Sync = {
com.gContactSync.Sync.finish("Max Contacts too low...resynchronizing", true);
return;
}
- com.gContactSync.Sync.mContactsToAdd = [];
+ com.gContactSync.Sync.mContactsToAdd = [];
+ com.gContactSync.Sync.mContactsToUploadPhoto = [];
com.gContactSync.Sync.mContactsToDelete = [];
com.gContactSync.Sync.mContactsToUpdate = [];
var gContact,
- // get the strings outside of the loop so they are only found once
- gContacts = {},
+ gContacts = {},
gContactInfo = {},
abCardInfo = [];
@@ -727,22 +729,15 @@ com.gContactSync.Sync = {
gcontact = new com.gContactSync.GContact(httpReq.responseXML);
contact.setValue('GoogleID', gcontact.getID(true));
contact.update();
- // if photos are allowed to be uploaded to Google then do so
- if (com.gContactSync.Preferences.mSyncPrefs.sendPhotos.value) {
- gcontact.setPhoto(com.gContactSync.Sync.mNewPhotoURI);
- }
- // reset the new photo URI variable
- com.gContactSync.Sync.mNewPhotoURI = null;
- // NOTE - Google has an undocumented limit on the rate at which photos
- // can be added. Add a small wait here.
+ // if photos are allowed to be uploaded to Google then queue the request
if (com.gContactSync.Preferences.mSyncPrefs.sendPhotos.value &&
- com.gContactSync.Preferences.mSyncPrefs.newContactPhotoDelay.value > 0) {
- setTimeout(com.gContactSync.Sync.processAddQueue,
- com.gContactSync.Preferences.mSyncPrefs.newContactPhotoDelay.value);
- } else {
- com.gContactSync.Sync.delayedProcessQueue(com.gContactSync.Sync.processAddQueue);
+ com.gContactSync.Sync.mNewPhotoURI) {
+ com.gContactSync.Sync.mContactsToUploadPhoto.push({abCard: com.gContactSync.ContactConverter.mCurrentCard,
+ gContact: gcontact,
+ uri: com.gContactSync.Sync.mNewPhotoURI});
}
- }
+ com.gContactSync.Sync.delayedProcessQueue(com.gContactSync.Sync.processAddQueue);
+ };
httpReq.mOnCreated = onCreated;
httpReq.mOnError = function contactCreatedError(httpReq) {
com.gContactSync.LOGGER.LOG_ERROR('Error while adding contact',
@@ -755,26 +750,21 @@ com.gContactSync.Sync = {
},
/**
* Updates all cards to Google included in the mContactsToUpdate array one at
- * a time to avoid timing conflicts. Calls
- * com.gContactSync.Sync.syncNextUser() when done.
+ * a time to avoid timing conflicts.
*/
processUpdateQueue: function Sync_processUpdateQueue() {
+
var ab = com.gContactSync.Sync.mCurrentAb;
- if (!com.gContactSync.Sync.mContactsToUpdate
- || com.gContactSync.Sync.mContactsToUpdate.length == 0
- || ab.mPrefs.readOnly == "true") {
- if (com.gContactSync.Sync.mAddressBooks[com.gContactSync.Sync.mIndex]) {
- var delay = com.gContactSync.Preferences.mSyncPrefs.accountDelay.value;
- com.gContactSync.LOGGER.LOG("**About to wait " + delay +
- " ms before synchronizing the next account**");
- com.gContactSync.Overlay.setStatusBarText(com.gContactSync.StringBundle.getStr("waiting"));
- setTimeout(com.gContactSync.Sync.syncNextUser, delay);
- }
- else {
- com.gContactSync.Sync.syncNextUser();
- }
+
+ if (!com.gContactSync.Sync.mContactsToUpdate ||
+ (com.gContactSync.Sync.mContactsToUpdate.length === 0) ||
+ (ab.mPrefs.readOnly === "true")) {
+
+ com.gContactSync.LOGGER.LOG("***Uploading contact photos to Google***");
+ com.gContactSync.Sync.processUpdatePhotoQueue();
return;
}
+
com.gContactSync.Overlay.setStatusBarText(com.gContactSync.StringBundle.getStr("updating") + " " +
com.gContactSync.Sync.mContactsToUpdate.length + " " +
com.gContactSync.StringBundle.getStr("remaining"));
@@ -792,8 +782,11 @@ com.gContactSync.Sync = {
}
var string = com.gContactSync.serialize(gContact.xml);
- if (com.gContactSync.Preferences.mSyncPrefs.verboseLog.value)
+ if (com.gContactSync.Preferences.mSyncPrefs.verboseLog.value) {
com.gContactSync.LOGGER.LOG(" * XML of contact being updated:\n" + string + "\n");
+ }
+ com.gContactSync.Sync.mNewPhotoURI = com.gContactSync.Preferences.mSyncPrefs.sendPhotos.value ?
+ gContact.mNewPhotoURI : null;
var httpReq = new com.gContactSync.GHttpRequest("update",
com.gContactSync.Sync.mCurrentAuthToken,
editURL,
@@ -801,6 +794,16 @@ com.gContactSync.Sync = {
com.gContactSync.Sync.mCurrentUsername);
httpReq.addHeaderItem("If-Match", "*");
httpReq.mOnSuccess = function processUpdateSuccess(httpReq) {
+
+ // if photos are allowed to be uploaded to Google then queue the request
+ if (com.gContactSync.Preferences.mSyncPrefs.sendPhotos.value &&
+ com.gContactSync.Sync.mNewPhotoURI) {
+
+ var gcontact = new com.gContactSync.GContact(httpReq.responseXML);
+ com.gContactSync.Sync.mContactsToUploadPhoto.push({abCard: com.gContactSync.ContactConverter.mCurrentCard,
+ gContact: gcontact,
+ uri: com.gContactSync.Sync.mNewPhotoURI});
+ }
com.gContactSync.Sync.delayedProcessQueue(com.gContactSync.Sync.processUpdateQueue);
};
httpReq.mOnError = function processUpdateError(httpReq) {
@@ -813,6 +816,38 @@ com.gContactSync.Sync = {
httpReq.send();
},
/**
+ * Uploads new and updated photos to Google.
+ * Calls com.gContactSync.Sync.syncNextUser() when done.
+ */
+ processUpdatePhotoQueue: function Sync_processUpdatePhotoQueue() {
+
+ var ab = com.gContactSync.Sync.mCurrentAb;
+
+ if (!com.gContactSync.Sync.mContactsToUploadPhoto ||
+ (com.gContactSync.Sync.mContactsToUploadPhoto.length === 0) ||
+ (ab.mPrefs.readOnly === "true")) {
+
+ if (com.gContactSync.Sync.mAddressBooks[com.gContactSync.Sync.mIndex]) {
+ var delay = com.gContactSync.Preferences.mSyncPrefs.accountDelay.value;
+ com.gContactSync.LOGGER.LOG("**About to wait " + delay +
+ " ms before synchronizing the next account**");
+ com.gContactSync.Overlay.setStatusBarText(com.gContactSync.StringBundle.getStr("waiting"));
+ setTimeout(com.gContactSync.Sync.syncNextUser, delay);
+ } else {
+ com.gContactSync.Sync.syncNextUser();
+ }
+ return;
+ }
+
+ com.gContactSync.Overlay.setStatusBarText(com.gContactSync.StringBundle.getStr("uploadingPhotos") + " " +
+ com.gContactSync.Sync.mContactsToAdd.length + " " +
+ com.gContactSync.StringBundle.getStr("remaining"));
+ var obj = com.gContactSync.Sync.mContactsToUploadPhoto.shift();
+ com.gContactSync.LOGGER.LOG("\n" + obj.abCard.getName());
+ obj.gContact.uploadPhoto(obj.uri);
+ com.gContactSync.Sync.delayedProcessQueue(com.gContactSync.Sync.processUpdatePhotoQueue);
+ },
+ /**
* Syncs all contact groups with mailing lists.
* @param aAtom {XML} The ATOM/XML feed of Groups.
*/
diff --git a/src/locale/en-US/gcontactsync.properties b/src/locale/en-US/gcontactsync.properties
index 0a4d73d..7b84606 100644
--- a/src/locale/en-US/gcontactsync.properties
+++ b/src/locale/en-US/gcontactsync.properties
@@ -20,6 +20,7 @@ waiting=Waiting to synchronize the next account...
deleting=Deleting contacts from Google:
updating=Updating contacts from Google:
adding=Adding contacts to Google:
+uploadingPhotos=Uploading photos to Google:
remaining=remaining.
pleaseAuth=Please login before trying to sync contacts.
offlineStatusText=Unable to sync contacts while offline.
--
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