Revision control
Copy as Markdown
Other Tools
/* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
var nsActProcess = Components.Constructor(
"@mozilla.org/activity-process;1",
"nsIActivityProcess",
"init"
);
var nsActEvent = Components.Constructor(
"@mozilla.org/activity-event;1",
"nsIActivityEvent",
"init"
);
var nsActWarning = Components.Constructor(
"@mozilla.org/activity-warning;1",
"nsIActivityWarning",
"init"
);
/**
* This really, really, sucks. Due to mailnews widespread use of
* nsIMsgStatusFeedback we're bound to the UI to get any sensible feedback of
* mail sending operations. The current send later code can't hook into the
* progress listener easily to get the state of messages being sent, so we'll
* just have to do it here.
*/
var sendMsgProgressListener = {
QueryInterface: ChromeUtils.generateQI([
"nsIMsgStatusFeedback",
"nsISupportsWeakReference",
]),
showStatusString(aStatusText) {
sendLaterModule.onMsgStatus(aStatusText);
},
startMeteors() {},
stopMeteors() {},
showProgress(aPercentage) {
sendLaterModule.onMessageSendProgress(0, 0, aPercentage, 0);
},
};
// This module provides a link between the send later service and the activity
// manager.
export var sendLaterModule = {
_sendProcess: null,
_copyProcess: null,
_identity: null,
_subject: null,
get log() {
delete this.log;
return (this.log = console.createInstance({
prefix: "mail.activity",
maxLogLevel: "Warn",
maxLogLevelPref: "mail.activity.loglevel",
}));
},
get activityMgr() {
delete this.activityMgr;
return (this.activityMgr = Cc["@mozilla.org/activity-manager;1"].getService(
Ci.nsIActivityManager
));
},
get bundle() {
delete this.bundle;
return (this.bundle = Services.strings.createBundle(
));
},
QueryInterface: ChromeUtils.generateQI(["nsIMsgSendLaterListener"]),
_displayTextForHeader(aLocaleStringBase, aSubject) {
return aSubject
? this.bundle.formatStringFromName(aLocaleStringBase + "WithSubject", [
aSubject,
])
: this.bundle.GetStringFromName(aLocaleStringBase);
},
_newProcess(aLocaleStringBase, aAddSubject) {
const process = new nsActProcess(
this._displayTextForHeader(
aLocaleStringBase,
aAddSubject ? this._subject : ""
),
this.activityMgr
);
process.iconClass = "sendMail";
process.groupingStyle = Ci.nsIActivity.GROUPING_STYLE_BYCONTEXT;
process.contextObj = this;
process.contextType = "SendLater";
process.contextDisplayText =
this.bundle.GetStringFromName("sendingMessages");
return process;
},
// Use this to group an activity by the identity if we have one.
_applyIdentityGrouping(aActivity) {
if (this._identity) {
aActivity.groupingStyle = Ci.nsIActivity.GROUPING_STYLE_BYCONTEXT;
aActivity.contextType = this._identity.key;
aActivity.contextObj = this._identity;
let contextDisplayText = this._identity.identityName;
if (!contextDisplayText) {
contextDisplayText = this._identity.email;
}
aActivity.contextDisplayText = contextDisplayText;
} else {
aActivity.groupingStyle = Ci.nsIActivity.GROUPING_STYLE_STANDALONE;
}
},
// Replaces the process with an event that reflects a completed process.
_replaceProcessWithEvent(aProcess) {
this.activityMgr.removeActivity(aProcess.id);
const event = new nsActEvent(
this._displayTextForHeader("sentMessage", this._subject),
this.activityMgr,
"",
aProcess.startTime,
new Date()
);
event.iconClass = "sendMail";
this._applyIdentityGrouping(event);
this.activityMgr.addActivity(event);
},
// Replaces the process with a warning that reflects the failed process.
_replaceProcessWithWarning(aProcess, aCopyOrSend) {
this.activityMgr.removeActivity(aProcess.id);
const warning = new nsActWarning(
this._displayTextForHeader("failedTo" + aCopyOrSend, this._subject),
this.activityMgr,
""
);
warning.groupingStyle = Ci.nsIActivity.GROUPING_STYLE_STANDALONE;
this._applyIdentityGrouping(warning);
this.activityMgr.addActivity(warning);
},
onStartSending(aTotalMessageCount) {
if (!aTotalMessageCount) {
this.log.error("onStartSending called with zero messages\n");
}
},
onMessageStartSending(
aCurrentMessage,
aTotalMessageCount,
aMessageHeader,
aIdentity
) {
// We want to use the identity and subject later, so store them for now.
this._identity = aIdentity;
if (aMessageHeader) {
this._subject = aMessageHeader.mime2DecodedSubject;
}
// Create the process to display the send activity.
let process = this._newProcess("sendingMessage", true);
this._sendProcess = process;
this.activityMgr.addActivity(process);
// Now the one for the copy process.
process = this._newProcess("copyMessage", false);
this._copyProcess = process;
this.activityMgr.addActivity(process);
},
onMessageSendProgress(
aCurrentMessage,
aTotalMessageCount,
aMessageSendPercent,
aMessageCopyPercent
) {
if (aMessageSendPercent < 100) {
// Ensure we are in progress...
if (this._sendProcess.state != Ci.nsIActivityProcess.STATE_INPROGRESS) {
this._sendProcess.state = Ci.nsIActivityProcess.STATE_INPROGRESS;
}
// ... and update the progress.
this._sendProcess.setProgress(
this._sendProcess.lastStatusText,
aMessageSendPercent,
100
);
} else if (aMessageSendPercent == 100) {
if (aMessageCopyPercent == 0) {
// Set send state to completed
if (this._sendProcess.state != Ci.nsIActivityProcess.STATE_COMPLETED) {
this._sendProcess.state = Ci.nsIActivityProcess.STATE_COMPLETED;
}
this._replaceProcessWithEvent(this._sendProcess);
// Set copy state to in progress.
if (this._copyProcess.state != Ci.nsIActivityProcess.STATE_INPROGRESS) {
this._copyProcess.state = Ci.nsIActivityProcess.STATE_INPROGRESS;
}
// We don't know the progress of the copy, so just set to 0, and we'll
// display an undetermined progress meter.
this._copyProcess.setProgress(this._copyProcess.lastStatusText, 0, 0);
} else if (aMessageCopyPercent >= 100) {
// We need to set this to completed otherwise activity manager
// complains.
if (this._copyProcess) {
this._copyProcess.state = Ci.nsIActivityProcess.STATE_COMPLETED;
this.activityMgr.removeActivity(this._copyProcess.id);
this._copyProcess = null;
}
this._sendProcess = null;
}
}
},
onMessageSendError(aCurrentMessage, aMessageHeader, aStatus, aMsg) {
if (
this._sendProcess &&
this._sendProcess.state != Ci.nsIActivityProcess.STATE_COMPLETED
) {
this._sendProcess.state = Ci.nsIActivityProcess.STATE_COMPLETED;
this._replaceProcessWithWarning(
this._sendProcess,
"SendMessage",
aStatus,
aMsg,
aMessageHeader
);
this._sendProcess = null;
if (
this._copyProcess &&
this._copyProcess.state != Ci.nsIActivityProcess.STATE_COMPLETED
) {
this._copyProcess.state = Ci.nsIActivityProcess.STATE_COMPLETED;
this.activityMgr.removeActivity(this._copyProcess.id);
this._copyProcess = null;
}
}
},
onMsgStatus(aStatusText) {
this._sendProcess.setProgress(
aStatusText,
this._sendProcess.workUnitComplete,
this._sendProcess.totalWorkUnits
);
},
onStopSending() {},
init() {
// We should need to remove the listener as we're not being held by anyone
// except by the send later instance.
const sendLaterService = Cc[
"@mozilla.org/messengercompose/sendlater;1"
].getService(Ci.nsIMsgSendLater);
sendLaterService.addListener(this);
// Also add the nsIMsgStatusFeedback object.
const statusFeedback = Cc[
"@mozilla.org/messenger/statusfeedback;1"
].createInstance(Ci.nsIMsgStatusFeedback);
statusFeedback.setWrappedStatusFeedback(sendMsgProgressListener);
sendLaterService.statusFeedback = statusFeedback;
},
};