diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mail/components/activity/modules/sendLater.jsm | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/comm/mail/components/activity/modules/sendLater.jsm b/comm/mail/components/activity/modules/sendLater.jsm new file mode 100644 index 0000000000..37027d96f1 --- /dev/null +++ b/comm/mail/components/activity/modules/sendLater.jsm @@ -0,0 +1,298 @@ +/* -*- 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 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const EXPORTED_SYMBOLS = ["sendLaterModule"]; + +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. +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( + "chrome://messenger/locale/activity.properties" + )); + }, + + QueryInterface: ChromeUtils.generateQI(["nsIMsgSendLaterListener"]), + + _displayTextForHeader(aLocaleStringBase, aSubject) { + return aSubject + ? this.bundle.formatStringFromName(aLocaleStringBase + "WithSubject", [ + aSubject, + ]) + : this.bundle.GetStringFromName(aLocaleStringBase); + }, + + _newProcess(aLocaleStringBase, aAddSubject) { + let 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); + + let 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, + aStatus, + aMsg, + aMessageHeader + ) { + this.activityMgr.removeActivity(aProcess.id); + + let 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(aStatus, aMsg, aTotalTried, aSuccessful) {}, + + init() { + // We should need to remove the listener as we're not being held by anyone + // except by the send later instance. + let sendLaterService = Cc[ + "@mozilla.org/messengercompose/sendlater;1" + ].getService(Ci.nsIMsgSendLater); + + sendLaterService.addListener(this); + + // Also add the nsIMsgStatusFeedback object. + let statusFeedback = Cc[ + "@mozilla.org/messenger/statusfeedback;1" + ].createInstance(Ci.nsIMsgStatusFeedback); + + statusFeedback.setWrappedStatusFeedback(sendMsgProgressListener); + + sendLaterService.statusFeedback = statusFeedback; + }, +}; |