summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/compose/src/nsMsgSendReport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/compose/src/nsMsgSendReport.cpp')
-rw-r--r--comm/mailnews/compose/src/nsMsgSendReport.cpp385
1 files changed, 385 insertions, 0 deletions
diff --git a/comm/mailnews/compose/src/nsMsgSendReport.cpp b/comm/mailnews/compose/src/nsMsgSendReport.cpp
new file mode 100644
index 0000000000..5cab724810
--- /dev/null
+++ b/comm/mailnews/compose/src/nsMsgSendReport.cpp
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; 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/. */
+
+#include "nsMsgSendReport.h"
+
+#include "msgCore.h"
+#include "nsIMsgCompose.h"
+#include "nsMsgPrompts.h"
+#include "nsError.h"
+#include "nsComposeStrings.h"
+#include "nsIStringBundle.h"
+#include "nsServiceManagerUtils.h"
+#include "mozilla/Components.h"
+
+NS_IMPL_ISUPPORTS(nsMsgProcessReport, nsIMsgProcessReport)
+
+nsMsgProcessReport::nsMsgProcessReport() { Reset(); }
+
+nsMsgProcessReport::~nsMsgProcessReport() {}
+
+/* attribute boolean proceeded; */
+NS_IMETHODIMP nsMsgProcessReport::GetProceeded(bool* aProceeded) {
+ NS_ENSURE_ARG_POINTER(aProceeded);
+ *aProceeded = mProceeded;
+ return NS_OK;
+}
+NS_IMETHODIMP nsMsgProcessReport::SetProceeded(bool aProceeded) {
+ mProceeded = aProceeded;
+ return NS_OK;
+}
+
+/* attribute nsresult error; */
+NS_IMETHODIMP nsMsgProcessReport::GetError(nsresult* aError) {
+ NS_ENSURE_ARG_POINTER(aError);
+ *aError = mError;
+ return NS_OK;
+}
+NS_IMETHODIMP nsMsgProcessReport::SetError(nsresult aError) {
+ mError = aError;
+ return NS_OK;
+}
+
+/* attribute wstring message; */
+NS_IMETHODIMP nsMsgProcessReport::GetMessage(char16_t** aMessage) {
+ NS_ENSURE_ARG_POINTER(aMessage);
+ *aMessage = ToNewUnicode(mMessage);
+ return NS_OK;
+}
+NS_IMETHODIMP nsMsgProcessReport::SetMessage(const char16_t* aMessage) {
+ mMessage = aMessage;
+ return NS_OK;
+}
+
+/* void Reset (); */
+NS_IMETHODIMP nsMsgProcessReport::Reset() {
+ mProceeded = false;
+ mError = NS_OK;
+ mMessage.Truncate();
+
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(nsMsgSendReport, nsIMsgSendReport)
+
+nsMsgSendReport::nsMsgSendReport() {
+ uint32_t i;
+ for (i = 0; i <= SEND_LAST_PROCESS; i++)
+ mProcessReport[i] = new nsMsgProcessReport();
+
+ Reset();
+}
+
+nsMsgSendReport::~nsMsgSendReport() {
+ uint32_t i;
+ for (i = 0; i <= SEND_LAST_PROCESS; i++) mProcessReport[i] = nullptr;
+}
+
+/* attribute long currentProcess; */
+NS_IMETHODIMP nsMsgSendReport::GetCurrentProcess(int32_t* aCurrentProcess) {
+ NS_ENSURE_ARG_POINTER(aCurrentProcess);
+ *aCurrentProcess = mCurrentProcess;
+ return NS_OK;
+}
+NS_IMETHODIMP nsMsgSendReport::SetCurrentProcess(int32_t aCurrentProcess) {
+ if (aCurrentProcess < 0 || aCurrentProcess > SEND_LAST_PROCESS)
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ mCurrentProcess = aCurrentProcess;
+ if (mProcessReport[mCurrentProcess])
+ mProcessReport[mCurrentProcess]->SetProceeded(true);
+
+ return NS_OK;
+}
+
+/* attribute long deliveryMode; */
+NS_IMETHODIMP nsMsgSendReport::GetDeliveryMode(int32_t* aDeliveryMode) {
+ NS_ENSURE_ARG_POINTER(aDeliveryMode);
+ *aDeliveryMode = mDeliveryMode;
+ return NS_OK;
+}
+NS_IMETHODIMP nsMsgSendReport::SetDeliveryMode(int32_t aDeliveryMode) {
+ mDeliveryMode = aDeliveryMode;
+ return NS_OK;
+}
+
+/* void Reset (); */
+NS_IMETHODIMP nsMsgSendReport::Reset() {
+ uint32_t i;
+ for (i = 0; i <= SEND_LAST_PROCESS; i++)
+ if (mProcessReport[i]) mProcessReport[i]->Reset();
+
+ mCurrentProcess = 0;
+ mDeliveryMode = 0;
+ mAlreadyDisplayReport = false;
+
+ return NS_OK;
+}
+
+/* void setProceeded (in long process, in boolean proceeded); */
+NS_IMETHODIMP nsMsgSendReport::SetProceeded(int32_t process, bool proceeded) {
+ if (process < process_Current || process > SEND_LAST_PROCESS)
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ if (process == process_Current) process = mCurrentProcess;
+
+ if (!mProcessReport[process]) return NS_ERROR_NOT_INITIALIZED;
+
+ return mProcessReport[process]->SetProceeded(proceeded);
+}
+
+/* void setError (in long process, in nsresult error, in boolean
+ * overwriteError); */
+NS_IMETHODIMP nsMsgSendReport::SetError(int32_t process, nsresult newError,
+ bool overwriteError) {
+ if (process < process_Current || process > SEND_LAST_PROCESS)
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ if (process == process_Current) {
+ if (mCurrentProcess == process_Current)
+ // We don't know what we're currently trying to do
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ process = mCurrentProcess;
+ }
+
+ if (!mProcessReport[process]) return NS_ERROR_NOT_INITIALIZED;
+
+ nsresult currError = NS_OK;
+ mProcessReport[process]->GetError(&currError);
+ if (overwriteError || NS_SUCCEEDED(currError))
+ return mProcessReport[process]->SetError(newError);
+ else
+ return NS_OK;
+}
+
+/* void setMessage (in long process, in wstring message, in boolean
+ * overwriteMessage); */
+NS_IMETHODIMP nsMsgSendReport::SetMessage(int32_t process,
+ const char16_t* message,
+ bool overwriteMessage) {
+ if (process < process_Current || process > SEND_LAST_PROCESS)
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ if (process == process_Current) {
+ if (mCurrentProcess == process_Current)
+ // We don't know what we're currently trying to do
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ process = mCurrentProcess;
+ }
+
+ if (!mProcessReport[process]) return NS_ERROR_NOT_INITIALIZED;
+
+ nsString currMessage;
+ mProcessReport[process]->GetMessage(getter_Copies(currMessage));
+ if (overwriteMessage || currMessage.IsEmpty())
+ return mProcessReport[process]->SetMessage(message);
+ else
+ return NS_OK;
+}
+
+/* nsIMsgProcessReport getProcessReport (in long process); */
+NS_IMETHODIMP nsMsgSendReport::GetProcessReport(int32_t process,
+ nsIMsgProcessReport** _retval) {
+ NS_ENSURE_ARG_POINTER(_retval);
+ if (process < process_Current || process > SEND_LAST_PROCESS)
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ if (process == process_Current) {
+ if (mCurrentProcess == process_Current)
+ // We don't know what we're currently trying to do
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ process = mCurrentProcess;
+ }
+
+ NS_IF_ADDREF(*_retval = mProcessReport[process]);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgSendReport::DisplayReport(mozIDOMWindowProxy* window,
+ bool showErrorOnly,
+ bool dontShowReportTwice,
+ nsresult* _retval) {
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ NS_ENSURE_TRUE(mCurrentProcess >= 0 && mCurrentProcess <= SEND_LAST_PROCESS,
+ NS_ERROR_NOT_INITIALIZED);
+
+ nsresult currError = NS_OK;
+ mProcessReport[mCurrentProcess]->GetError(&currError);
+ *_retval = currError;
+
+ if (dontShowReportTwice && mAlreadyDisplayReport) return NS_OK;
+
+ if (showErrorOnly && NS_SUCCEEDED(currError)) return NS_OK;
+
+ nsString currMessage;
+ mProcessReport[mCurrentProcess]->GetMessage(getter_Copies(currMessage));
+
+ nsresult rv; // don't step on currError.
+ nsCOMPtr<nsIStringBundleService> bundleService =
+ mozilla::components::StringBundle::Service();
+ NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
+ nsCOMPtr<nsIStringBundle> bundle;
+ rv = bundleService->CreateBundle(
+ "chrome://messenger/locale/messengercompose/composeMsgs.properties",
+ getter_AddRefs(bundle));
+ if (NS_FAILED(rv)) {
+ // TODO need to display a generic hardcoded message
+ mAlreadyDisplayReport = true;
+ return NS_OK;
+ }
+
+ nsString dialogTitle;
+ nsString dialogMessage;
+
+ if (NS_SUCCEEDED(currError)) {
+ // TODO display a success error message
+ return NS_OK;
+ }
+
+ // Do we have an explanation of the error? if no, try to build one...
+ if (currMessage.IsEmpty()) {
+#ifdef __GNUC__
+// Temporary workaround until bug 783526 is fixed.
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wswitch"
+#endif
+ switch (currError) {
+ case NS_BINDING_ABORTED:
+ case NS_MSG_UNABLE_TO_SEND_LATER:
+ case NS_MSG_UNABLE_TO_SAVE_DRAFT:
+ case NS_MSG_UNABLE_TO_SAVE_TEMPLATE:
+ // Ignore, don't need to repeat ourself.
+ break;
+ default:
+ const char* errorString = errorStringNameForErrorCode(currError);
+ nsMsgGetMessageByName(errorString, currMessage);
+ break;
+ }
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+ }
+
+ if (mDeliveryMode == nsIMsgCompDeliverMode::Now ||
+ mDeliveryMode == nsIMsgCompDeliverMode::SendUnsent) {
+ // SMTP is taking care of it's own error message and will return
+ // NS_ERROR_BUT_DONT_SHOW_ALERT as error code. In that case, we must not
+ // show an alert ourself.
+ if (currError == NS_ERROR_BUT_DONT_SHOW_ALERT) {
+ mAlreadyDisplayReport = true;
+ return NS_OK;
+ }
+
+ bundle->GetStringFromName("sendMessageErrorTitle", dialogTitle);
+
+ const char* preStrName = "sendFailed";
+ bool askToGoBackToCompose = false;
+ switch (mCurrentProcess) {
+ case process_BuildMessage:
+ preStrName = "sendFailed";
+ askToGoBackToCompose = false;
+ break;
+ case process_NNTP:
+ preStrName = "sendFailed";
+ askToGoBackToCompose = false;
+ break;
+ case process_SMTP:
+ bool nntpProceeded;
+ mProcessReport[process_NNTP]->GetProceeded(&nntpProceeded);
+ if (nntpProceeded)
+ preStrName = "sendFailedButNntpOk";
+ else
+ preStrName = "sendFailed";
+ askToGoBackToCompose = false;
+ break;
+ case process_Copy:
+ preStrName = "failedCopyOperation";
+ askToGoBackToCompose = (mDeliveryMode == nsIMsgCompDeliverMode::Now);
+ break;
+ case process_FCC:
+ preStrName = "failedCopyOperation";
+ askToGoBackToCompose = (mDeliveryMode == nsIMsgCompDeliverMode::Now);
+ break;
+ }
+ bundle->GetStringFromName(preStrName, dialogMessage);
+
+ // Do we already have an error message?
+ if (!askToGoBackToCompose && currMessage.IsEmpty()) {
+ // we don't have an error description but we can put a generic explanation
+ bundle->GetStringFromName("genericFailureExplanation", currMessage);
+ }
+
+ if (!currMessage.IsEmpty()) {
+ // Don't need to repeat ourself!
+ if (!currMessage.Equals(dialogMessage)) {
+ if (!dialogMessage.IsEmpty()) dialogMessage.Append(char16_t('\n'));
+ dialogMessage.Append(currMessage);
+ }
+ }
+
+ if (askToGoBackToCompose) {
+ bool oopsGiveMeBackTheComposeWindow = true;
+ nsString text1;
+ bundle->GetStringFromName("returnToComposeWindowQuestion", text1);
+ if (!dialogMessage.IsEmpty()) dialogMessage.AppendLiteral("\n");
+ dialogMessage.Append(text1);
+ nsMsgAskBooleanQuestionByString(window, dialogMessage.get(),
+ &oopsGiveMeBackTheComposeWindow,
+ dialogTitle.get());
+ if (!oopsGiveMeBackTheComposeWindow) *_retval = NS_OK;
+ } else
+ nsMsgDisplayMessageByString(window, dialogMessage.get(),
+ dialogTitle.get());
+ } else {
+ const char* title;
+ const char* messageName;
+
+ switch (mDeliveryMode) {
+ case nsIMsgCompDeliverMode::Later:
+ title = "sendLaterErrorTitle";
+ messageName = "unableToSendLater";
+ break;
+
+ case nsIMsgCompDeliverMode::AutoSaveAsDraft:
+ case nsIMsgCompDeliverMode::SaveAsDraft:
+ title = "saveDraftErrorTitle";
+ messageName = "unableToSaveDraft";
+ break;
+
+ case nsIMsgCompDeliverMode::SaveAsTemplate:
+ title = "saveTemplateErrorTitle";
+ messageName = "unableToSaveTemplate";
+ break;
+
+ default:
+ /* This should never happen! */
+ title = "sendMessageErrorTitle";
+ messageName = "sendFailed";
+ break;
+ }
+
+ bundle->GetStringFromName(title, dialogTitle);
+ bundle->GetStringFromName(messageName, dialogMessage);
+
+ // Do we have an error message...
+ if (currMessage.IsEmpty()) {
+ // we don't have an error description but we can put a generic explanation
+ bundle->GetStringFromName("genericFailureExplanation", currMessage);
+ }
+
+ if (!currMessage.IsEmpty()) {
+ if (!dialogMessage.IsEmpty()) dialogMessage.Append(char16_t('\n'));
+ dialogMessage.Append(currMessage);
+ }
+ nsMsgDisplayMessageByString(window, dialogMessage.get(), dialogTitle.get());
+ }
+
+ mAlreadyDisplayReport = true;
+ return NS_OK;
+}