summaryrefslogtreecommitdiffstats
path: root/mailnews/compose/src/nsMsgSendReport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/compose/src/nsMsgSendReport.cpp')
-rw-r--r--mailnews/compose/src/nsMsgSendReport.cpp437
1 files changed, 437 insertions, 0 deletions
diff --git a/mailnews/compose/src/nsMsgSendReport.cpp b/mailnews/compose/src/nsMsgSendReport.cpp
new file mode 100644
index 000000000..1bc26ca8a
--- /dev/null
+++ b/mailnews/compose/src/nsMsgSendReport.cpp
@@ -0,0 +1,437 @@
+/* -*- 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 "nsMsgCompCID.h"
+#include "nsMsgPrompts.h"
+#include "nsError.h"
+#include "nsComposeStrings.h"
+#include "nsIStringBundle.h"
+#include "nsServiceManagerUtils.h"
+#include "mozilla/Services.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;
+}
+
+/* nsresult displayReport (in nsIPrompt prompt, in boolean showErrorOnly, in boolean dontShowReportTwice); */
+NS_IMETHODIMP nsMsgSendReport::DisplayReport(nsIPrompt *prompt, 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::services::GetStringBundleService();
+ 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 workaroung until bug 783526 is fixed.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+#endif
+ switch (currError)
+ {
+ case NS_BINDING_ABORTED:
+ case NS_ERROR_SEND_FAILED:
+ case NS_ERROR_SEND_FAILED_BUT_NNTP_OK:
+ case NS_MSG_FAILED_COPY_OPERATION:
+ 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 char16_t* 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(u"sendMessageErrorTitle",
+ getter_Copies(dialogTitle));
+
+ const char16_t* preStrName = u"sendFailed";
+ bool askToGoBackToCompose = false;
+ switch (mCurrentProcess)
+ {
+ case process_BuildMessage :
+ preStrName = u"sendFailed";
+ askToGoBackToCompose = false;
+ break;
+ case process_NNTP :
+ preStrName = u"sendFailed";
+ askToGoBackToCompose = false;
+ break;
+ case process_SMTP :
+ bool nntpProceeded;
+ mProcessReport[process_NNTP]->GetProceeded(&nntpProceeded);
+ if (nntpProceeded)
+ preStrName = u"sendFailedButNntpOk";
+ else
+ preStrName = u"sendFailed";
+ askToGoBackToCompose = false;
+ break;
+ case process_Copy:
+ preStrName = u"failedCopyOperation";
+ askToGoBackToCompose = (mDeliveryMode == nsIMsgCompDeliverMode::Now);
+ break;
+ case process_FCC:
+ preStrName = u"failedCopyOperation";
+ askToGoBackToCompose = (mDeliveryMode == nsIMsgCompDeliverMode::Now);
+ break;
+ }
+ bundle->GetStringFromName(preStrName, getter_Copies(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(u"genericFailureExplanation",
+ getter_Copies(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(u"returnToComposeWindowQuestion",
+ getter_Copies(text1));
+ if (!dialogMessage.IsEmpty())
+ dialogMessage.AppendLiteral("\n");
+ dialogMessage.Append(text1);
+ nsMsgAskBooleanQuestionByString(prompt, dialogMessage.get(), &oopsGiveMeBackTheComposeWindow, dialogTitle.get());
+ if (!oopsGiveMeBackTheComposeWindow)
+ *_retval = NS_OK;
+ }
+ else
+ nsMsgDisplayMessageByString(prompt, dialogMessage.get(), dialogTitle.get());
+ }
+ else
+ {
+ const char16_t* title;
+ const char16_t* messageName;
+
+ switch (mDeliveryMode)
+ {
+ case nsIMsgCompDeliverMode::Later:
+ title = u"sendLaterErrorTitle";
+ messageName = u"unableToSendLater";
+ break;
+
+ case nsIMsgCompDeliverMode::AutoSaveAsDraft:
+ case nsIMsgCompDeliverMode::SaveAsDraft:
+ title = u"saveDraftErrorTitle";
+ messageName = u"unableToSaveDraft";
+ break;
+
+ case nsIMsgCompDeliverMode::SaveAsTemplate:
+ title = u"saveTemplateErrorTitle";
+ messageName = u"unableToSaveTemplate";
+ break;
+
+ default:
+ /* This should never happen! */
+ title = u"sendMessageErrorTitle";
+ messageName = u"sendFailed";
+ break;
+ }
+
+ bundle->GetStringFromName(title, getter_Copies(dialogTitle));
+ bundle->GetStringFromName(messageName,
+ getter_Copies(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(u"genericFailureExplanation",
+ getter_Copies(currMessage));
+ }
+
+ if (!currMessage.IsEmpty())
+ {
+ if (!dialogMessage.IsEmpty())
+ dialogMessage.Append(char16_t('\n'));
+ dialogMessage.Append(currMessage);
+ }
+ nsMsgDisplayMessageByString(prompt, dialogMessage.get(), dialogTitle.get());
+ }
+
+ mAlreadyDisplayReport = true;
+ return NS_OK;
+}
+