Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
188 lines
6.4 KiB
JavaScript
Executable file
188 lines
6.4 KiB
JavaScript
Executable file
define(['module', 'exports', 'logic', '../allback', 'mix',
|
|
'../jobmixins', '../drafts/jobs', './pop3'],
|
|
function(module, exports, logic, allback, mix,
|
|
jobmixins, draftsJobs, pop3) {
|
|
|
|
/**
|
|
* Manage the jobs for a POP3 account. POP3 does not support
|
|
* server-side folders, so many of these operations are local-only.
|
|
* Operations not implemented in the Pop3JobDriver are ignored and
|
|
* assumed unsupported. For instance, issuing a "move" command will
|
|
* execute local_do_move, but not do_move. It is assumed that unit
|
|
* tests will ensure we've implemented all required jobs.
|
|
*/
|
|
function Pop3JobDriver(account, state) {
|
|
this.account = account;
|
|
this.resilientServerIds = true; // once assigned, the server never changes IDs
|
|
this._heldMutexReleasers = [];
|
|
|
|
logic.defineScope(this, 'Pop3JobDriver', { accountId: account.id });
|
|
|
|
// For tracking state as used in jobmixins:
|
|
this._stateDelta = {};
|
|
this._state = state;
|
|
if (!state.hasOwnProperty('suidToServerId')) {
|
|
state.suidToServerId = {};
|
|
state.moveMap = {};
|
|
}
|
|
}
|
|
exports.Pop3JobDriver = Pop3JobDriver;
|
|
Pop3JobDriver.prototype = {
|
|
|
|
/**
|
|
* Request access to a POP3 folder for mutation. This acquires a
|
|
* write mutex on the FolderStorage. The callback will be invoked
|
|
* with the folder and the raw connection.
|
|
*
|
|
* There is no need to explicitly release the connection when done;
|
|
* it will be automatically released when the mutex is released if
|
|
* desirable.
|
|
*
|
|
* This function is used by jobmixins.
|
|
*/
|
|
_accessFolderForMutation: function(
|
|
folderId, needConn, callback, deathback, label) {
|
|
var storage = this.account.getFolderStorageForFolderId(folderId);
|
|
storage.runMutexed(label, function(releaseMutex) {
|
|
this._heldMutexReleasers.push(releaseMutex);
|
|
try {
|
|
// The folderSyncer is like IMAP/ActiveSync's folderConn.
|
|
callback(storage.folderSyncer, storage);
|
|
} catch (ex) {
|
|
logic(this, 'callbackErr', { ex: ex });
|
|
}
|
|
}.bind(this));
|
|
},
|
|
|
|
/**
|
|
* Create a folder locally. (Again, no remote folders, so
|
|
* do_createFolder is not implemented.)
|
|
*/
|
|
local_do_createFolder: function(op, callback) {
|
|
var path, delim, parentFolderId = null, depth = 0;
|
|
|
|
if (op.parentFolderId) {
|
|
if (!this.account._folderInfos.hasOwnProperty(op.parentFolderId)) {
|
|
throw new Error("No such folder: " + op.parentFolderId);
|
|
}
|
|
var parentFolder = this.account._folderInfos[op.parentFolderId];
|
|
delim = parentFolder.$meta.delim;
|
|
path = parentFolder.$meta.path + delim;
|
|
parentFolderId = parentFolder.$meta.id;
|
|
depth = parentFolder.depth + 1;
|
|
}
|
|
else {
|
|
path = '';
|
|
delim = '/';
|
|
}
|
|
|
|
if (typeof(op.folderName) === 'string')
|
|
path += op.folderName;
|
|
else
|
|
path += op.folderName.join(delim);
|
|
if (op.containOnlyOtherFolders) {
|
|
path += delim;
|
|
}
|
|
|
|
if (this.account.getFolderByPath(path)) {
|
|
callback(null);
|
|
} else {
|
|
var folderMeta = self.account._learnAboutFolder(
|
|
op.folderName, path, parentFolderId, 'normal', delim, depth);
|
|
callback(null, folderMeta);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Delete old messages from disk. Since we currently leave mail on
|
|
* the server, we won't incur permanent data loss.
|
|
*/
|
|
local_do_purgeExcessMessages: function(op, callback) {
|
|
this._accessFolderForMutation(
|
|
op.folderId, false,
|
|
function withMutex(_ignoredConn, storage) {
|
|
storage.purgeExcessMessages(function(numDeleted, cutTS) {
|
|
// Indicate that we want a save performed if any messages got deleted.
|
|
callback(null, null, numDeleted > 0);
|
|
});
|
|
},
|
|
null,
|
|
'purgeExcessMessages');
|
|
},
|
|
|
|
local_do_saveSentDraft: function(op, callback) {
|
|
var self = this;
|
|
this._accessFolderForMutation(
|
|
op.folderId, /* needConn*/ false,
|
|
function(nullFolderConn, folderStorage) {
|
|
var latch = allback.latch();
|
|
|
|
folderStorage.addMessageHeader(op.headerInfo, op.bodyInfo,
|
|
latch.defer());
|
|
folderStorage.addMessageBody(op.headerInfo, op.bodyInfo, latch.defer());
|
|
|
|
latch.then(function(results) {
|
|
// header/body insertion can't fail
|
|
callback(null, null, /* save */ true);
|
|
});
|
|
},
|
|
/* no conn => no deathback required */ null,
|
|
'saveSentDraft');
|
|
},
|
|
|
|
do_syncFolderList: function(op, doneCallback) {
|
|
this.account.meta.lastFolderSyncAt = Date.now();
|
|
doneCallback(null);
|
|
},
|
|
|
|
/** No-op to silence warnings. Perhaps implement someday. */
|
|
do_modtags: function(op, doneCallback) {
|
|
doneCallback(null);
|
|
},
|
|
|
|
/** No-op to silence warnings. Perhaps implement someday. */
|
|
undo_modtags: function(op, doneCallback) {
|
|
doneCallback(null);
|
|
},
|
|
|
|
// Local modifications (move, delete, and modtags) simply reuse the
|
|
// jobmixins implementation. No server-side implementations are
|
|
// necessary here, so they are omitted.
|
|
local_do_modtags: jobmixins.local_do_modtags,
|
|
local_undo_modtags: jobmixins.local_undo_modtags,
|
|
local_do_move: jobmixins.local_do_move,
|
|
local_undo_move: jobmixins.local_undo_move,
|
|
local_do_delete: jobmixins.local_do_delete,
|
|
local_undo_delete: jobmixins.local_undo_delete,
|
|
|
|
// Download operations (for attachments) are irrelevant because
|
|
// downloading the bodies always fetches the attachments too.
|
|
|
|
local_do_downloadBodies: jobmixins.local_do_downloadBodies,
|
|
do_downloadBodies: jobmixins.do_downloadBodies,
|
|
check_downloadBodies: jobmixins.check_downloadBodies,
|
|
|
|
check_downloadBodyReps: jobmixins.check_downloadBodyReps,
|
|
do_downloadBodyReps: jobmixins.do_downloadBodyReps,
|
|
local_do_downloadBodyReps: jobmixins.local_do_downloadBodyReps,
|
|
|
|
|
|
local_do_sendOutboxMessages: jobmixins.local_do_sendOutboxMessages,
|
|
do_sendOutboxMessages: jobmixins.do_sendOutboxMessages,
|
|
check_sendOutboxMessages: jobmixins.check_sendOutboxMessages,
|
|
local_undo_sendOutboxMessages: jobmixins.local_undo_sendOutboxMessages,
|
|
undo_sendOutboxMessages: jobmixins.undo_sendOutboxMessages,
|
|
local_do_setOutboxSyncEnabled: jobmixins.local_do_setOutboxSyncEnabled,
|
|
|
|
local_do_upgradeDB: jobmixins.local_do_upgradeDB,
|
|
|
|
// These utility functions are necessary.
|
|
postJobCleanup: jobmixins.postJobCleanup,
|
|
allJobsDone: jobmixins.allJobsDone,
|
|
_partitionAndAccessFoldersSequentially:
|
|
jobmixins._partitionAndAccessFoldersSequentially
|
|
};
|
|
|
|
mix(Pop3JobDriver.prototype, draftsJobs.draftsMixins);
|
|
|
|
}); // end define
|