Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge pull request #7344 from mozsquib/email-as-move

Bug 826585 - [email/activesync] Deleting/moving messages causes them to show up twice in the target folder
  • Loading branch information...
commit 31737604a2ba0accb7ae3f18d086f33e873decc4 2 parents e95e507 + 3b372ee
Jim Porter jimporter authored

Showing 1 changed file with 66 additions and 24 deletions. Show diff stats Hide diff stats

  1. +66 24 apps/email/js/ext/gaia-email-opt.js
90 apps/email/js/ext/gaia-email-opt.js
@@ -26699,6 +26699,19 @@ FolderStorage.prototype = {
26699 26699 this._curSyncSlice.onHeaderAdded(header, true, false);
26700 26700 },
26701 26701
  26702 + hasMessageWithServerId: function(srvid) {
  26703 + if (!this._serverIdHeaderBlockMapping)
  26704 + throw new Error('Server ID mapping not supported for this storage!');
  26705 +
  26706 + var blockId = this._serverIdHeaderBlockMapping[srvid];
  26707 + if (srvid === undefined) {
  26708 + this._LOG.serverIdMappingMissing(srvid);
  26709 + return false;
  26710 + }
  26711 +
  26712 + return !!blockId;
  26713 + },
  26714 +
26702 26715 deleteMessageHeaderAndBody: function(header, callback) {
26703 26716 if (this._pendingLoads.length) {
26704 26717 this._deferredCalls.push(this.deleteMessageHeaderAndBody.bind(
@@ -32707,7 +32720,6 @@ function FakeAccount(universe, accountDef, folderInfo, receiveProtoConn, _LOG) {
32707 32720
32708 32721 this.meta = folderInfo.$meta;
32709 32722 this.mutations = folderInfo.$mutations;
32710   - this.deferredMutations = folderInfo.$deferredMutations;
32711 32723 }
32712 32724 exports.FakeAccount = FakeAccount;
32713 32725 FakeAccount.prototype = {
@@ -33588,29 +33600,53 @@ ActiveSyncFolderConn.prototype = {
33588 33600 return;
33589 33601 }
33590 33602
  33603 + let addedMessages = 0;
33591 33604 for (let [,message] in Iterator(added)) {
  33605 + // If we already have this message, it's probably because we moved it as
  33606 + // part of a local op, so let's assume that the data we already have is
  33607 + // ok. XXX: We might want to verify this, to be safe.
  33608 + if (storage.hasMessageWithServerId(message.header.srvid))
  33609 + continue;
  33610 +
33592 33611 storage.addMessageHeader(message.header);
33593 33612 storage.addMessageBody(message.header, message.body);
  33613 + addedMessages++;
33594 33614 }
33595 33615
  33616 + let changedMessages = 0;
33596 33617 for (let [,message] in Iterator(changed)) {
  33618 + // If we don't know about this message, just bail out.
  33619 + if (!storage.hasMessageWithServerId(message.header.srvid))
  33620 + continue;
  33621 +
33597 33622 storage.updateMessageHeaderByServerId(message.header.srvid, true,
33598 33623 function(oldHeader) {
33599 33624 message.header.mergeInto(oldHeader);
33600 33625 return true;
33601 33626 });
  33627 + changedMessages++;
33602 33628 // XXX: update bodies
33603 33629 }
33604 33630
  33631 + let deletedMessages = 0;
33605 33632 for (let [,messageGuid] in Iterator(deleted)) {
  33633 + // If we don't know about this message, it's probably because we already
  33634 + // deleted it.
  33635 + if (!storage.hasMessageWithServerId(messageGuid))
  33636 + continue;
  33637 +
33606 33638 storage.deleteMessageByServerId(messageGuid);
  33639 + deletedMessages++;
33607 33640 }
33608 33641
33609   - messagesSeen += added.length + changed.length + deleted.length;
  33642 + messagesSeen += addedMessages + changedMessages + deletedMessages;
33610 33643
33611 33644 if (!moreAvailable) {
33612   - folderConn._LOG.syncDateRange_end(added.length, changed.length,
33613   - deleted.length, startTS, endTS);
  33645 + // Note: For the second argument here, we report the number of messages
  33646 + // we saw that *changed*. This differs from IMAP, which reports the
  33647 + // number of messages it *saw*.
  33648 + folderConn._LOG.syncDateRange_end(addedMessages, changedMessages,
  33649 + deletedMessages, startTS, endTS);
33614 33650 storage.markSyncRange(startTS, endTS, 'XXX', accuracyStamp);
33615 33651 doneCallback(null, null, messagesSeen);
33616 33652 }
@@ -33688,7 +33724,7 @@ ActiveSyncFolderConn.prototype = {
33688 33724 e.run(aResponse);
33689 33725 }
33690 33726 catch (ex) {
33691   - console.error('Error parsing Sync reponse:', ex, '\n', ex.stack);
  33727 + console.error('Error parsing Sync response:', ex, '\n', ex.stack);
33692 33728 callWhenDone('unknown');
33693 33729 return;
33694 33730 }
@@ -34051,17 +34087,21 @@ ActiveSyncJobDriver.prototype = {
34051 34087 if (--modsToGo === 0)
34052 34088 callWhenDone();
34053 34089 }
  34090 +
  34091 + // Filter out any offline headers, since the server naturally can't do
  34092 + // anything for them. If this means we have no headers at all, just bail
  34093 + // out.
  34094 + serverIds = serverIds.filter(function(srvid) { return !!srvid; });
  34095 + if (!serverIds.length) {
  34096 + callWhenDone();
  34097 + return;
  34098 + }
  34099 +
34054 34100 folderConn.performMutation(
34055 34101 function withWriter(w) {
34056 34102 for (let i = 0; i < serverIds.length; i++) {
34057   - let srvid = serverIds[i];
34058   - // If the header is somehow an offline header, it will be null and
34059   - // there is nothing we can really do for it.
34060   - if (!srvid)
34061   - continue;
34062   -
34063 34103 w.stag(as.Change)
34064   - .tag(as.ServerId, srvid)
  34104 + .tag(as.ServerId, serverIds[i])
34065 34105 .stag(as.ApplicationData);
34066 34106
34067 34107 if (markRead !== undefined)
@@ -34124,8 +34164,6 @@ ActiveSyncJobDriver.prototype = {
34124 34164 let aggrErr = null, account = this.account,
34125 34165 targetFolderStorage = this.account.getFolderStorageForFolderId(
34126 34166 op.targetFolder);
34127   - const as = $ascp.AirSync.Tags;
34128   - const em = $ascp.Email.Tags;
34129 34167 const mo = $ascp.Move.Tags;
34130 34168
34131 34169 this._partitionAndAccessFoldersSequentially(
@@ -34134,17 +34172,21 @@ ActiveSyncJobDriver.prototype = {
34134 34172 let w = new $wbxml.Writer('1.3', 1, 'UTF-8');
34135 34173 w.stag(mo.MoveItems);
34136 34174
  34175 + // Filter out any offline headers, since the server naturally can't do
  34176 + // anything for them. If this means we have no headers at all, just bail
  34177 + // out.
  34178 + serverIds = serverIds.filter(function(srvid) { return !!srvid; });
  34179 + if (!serverIds.length) {
  34180 + callWhenDone();
  34181 + return;
  34182 + }
  34183 +
34137 34184 for (let i = 0; i < serverIds.length; i++) {
34138   - let srvid = serverIds[i];
34139   - // If the header is somehow an offline header, it will be null and
34140   - // there is nothing we can really do for it.
34141   - if (!srvid)
34142   - continue;
34143 34185 w.stag(mo.Move)
34144   - .tag(mo.SrcMsgId, srvid)
34145   - .tag(mo.SrcFldId, storage.folderMeta.serverId)
34146   - .tag(mo.DstFldId, targetFolderStorage.folderMeta.serverId)
34147   - .etag(mo.Move);
  34186 + .tag(mo.SrcMsgId, serverIds[i])
  34187 + .tag(mo.SrcFldId, storage.folderMeta.serverId)
  34188 + .tag(mo.DstFldId, targetFolderStorage.folderMeta.serverId)
  34189 + .etag(mo.Move);
34148 34190 }
34149 34191 w.etag(mo.MoveItems);
34150 34192
@@ -37237,7 +37279,7 @@ MailUniverse.prototype = {
37237 37279 * and transferred across to the non-deferred queue at account-load time.
37238 37280 */
37239 37281 _deferOp: function(account, op) {
37240   - account.deferredMutations.push(op.longtermId);
  37282 + this._opsByAccount[account.id].deferred.push(op.longtermId);
37241 37283 if (this._deferredOpTimeout !== null)
37242 37284 this._deferredOpTimeout = window.setTimeout(
37243 37285 this._boundQueueDeferredOps, $syncbase.DEFERRED_OP_DELAY_MS);

0 comments on commit 3173760

Please sign in to comment.
Something went wrong with that request. Please try again.