Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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 "nsMsgProgress.h"
#include "nsIBaseWindow.h"
#include "nsXPCOM.h"
#include "nsIMutableArray.h"
#include "nsISupportsPrimitives.h"
#include "nsIComponentManager.h"
#include "nsError.h"
#include "nsIWindowWatcher.h"
#include "nsPIDOMWindow.h"
#include "mozIDOMWindow.h"
#include "nsServiceManagerUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsMsgUtils.h"
#include "mozilla/Components.h"
#include "mozilla/dom/BrowsingContext.h"
NS_IMPL_ISUPPORTS(nsMsgProgress, nsIMsgStatusFeedback, nsIMsgProgress,
nsIWebProgressListener, nsIProgressEventSink,
nsISupportsWeakReference)
nsMsgProgress::nsMsgProgress() {
m_closeProgress = false;
m_processCanceled = false;
m_pendingStateFlags = -1;
m_pendingStateValue = NS_OK;
}
nsMsgProgress::~nsMsgProgress() { (void)ReleaseListeners(); }
NS_IMETHODIMP nsMsgProgress::OpenProgressDialog(
mozIDOMWindowProxy* parentDOMWindow, nsIMsgWindow* aMsgWindow,
const char* dialogURL, bool inDisplayModal, nsISupports* parameters) {
nsresult rv;
if (aMsgWindow) {
SetMsgWindow(aMsgWindow);
aMsgWindow->SetStatusFeedback(this);
}
NS_ENSURE_ARG_POINTER(dialogURL);
NS_ENSURE_ARG_POINTER(parentDOMWindow);
nsCOMPtr<nsPIDOMWindowOuter> parent =
nsPIDOMWindowOuter::From(parentDOMWindow);
// Set up window.arguments[0]...
nsCOMPtr<nsIMutableArray> array(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsInterfacePointer> ifptr =
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
ifptr->SetData(static_cast<nsIMsgProgress*>(this));
ifptr->SetDataIID(&NS_GET_IID(nsIMsgProgress));
array->AppendElement(ifptr);
array->AppendElement(parameters);
// Open the dialog.
RefPtr<mozilla::dom::BrowsingContext> newWindow;
nsString chromeOptions(u"chrome,dependent,centerscreen"_ns);
if (inDisplayModal) chromeOptions.AppendLiteral(",modal");
return parent->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL), u"_blank"_ns,
chromeOptions, array, getter_AddRefs(newWindow));
}
NS_IMETHODIMP nsMsgProgress::CloseProgressDialog(bool forceClose) {
m_closeProgress = true;
return OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP,
forceClose ? NS_ERROR_FAILURE : NS_OK);
}
NS_IMETHODIMP nsMsgProgress::GetProcessCanceledByUser(
bool* aProcessCanceledByUser) {
NS_ENSURE_ARG_POINTER(aProcessCanceledByUser);
*aProcessCanceledByUser = m_processCanceled;
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::SetProcessCanceledByUser(
bool aProcessCanceledByUser) {
m_processCanceled = aProcessCanceledByUser;
OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP,
NS_BINDING_ABORTED);
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::RegisterListener(
nsIWebProgressListener* listener) {
if (!listener) // Nothing to do with a null listener!
return NS_OK;
NS_ENSURE_ARG(this != listener); // Check for self-reference (see bug 271700)
m_listenerList.AppendObject(listener);
if (m_closeProgress || m_processCanceled)
listener->OnStateChange(nullptr, nullptr,
nsIWebProgressListener::STATE_STOP, NS_OK);
else {
listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
if (m_pendingStateFlags != -1)
listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags,
m_pendingStateValue);
}
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::UnregisterListener(
nsIWebProgressListener* listener) {
if (listener) m_listenerList.RemoveObject(listener);
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aStateFlags,
nsresult aStatus) {
m_pendingStateFlags = aStateFlags;
m_pendingStateValue = aStatus;
nsCOMPtr<nsIMsgWindow> msgWindow(do_QueryReferent(m_msgWindow));
if (aStateFlags == nsIWebProgressListener::STATE_STOP && msgWindow &&
NS_FAILED(aStatus)) {
msgWindow->StopUrls();
msgWindow->SetStatusFeedback(nullptr);
}
for (int32_t i = m_listenerList.Count() - 1; i >= 0; i--)
m_listenerList[i]->OnStateChange(aWebProgress, aRequest, aStateFlags,
aStatus);
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::OnProgressChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress) {
for (int32_t i = m_listenerList.Count() - 1; i >= 0; i--)
m_listenerList[i]->OnProgressChange(aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI* location,
uint32_t aFlags) {
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage) {
if (aMessage && *aMessage) m_pendingStatus = aMessage;
for (int32_t i = m_listenerList.Count() - 1; i >= 0; i--)
m_listenerList[i]->OnStatusChange(aWebProgress, aRequest, aStatus,
aMessage);
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::OnSecurityChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t state) {
return NS_OK;
}
NS_IMETHODIMP
nsMsgProgress::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, uint32_t aEvent) {
return NS_OK;
}
nsresult nsMsgProgress::ReleaseListeners() {
m_listenerList.Clear();
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::ShowStatusString(const nsAString& aStatus) {
return OnStatusChange(nullptr, nullptr, NS_OK,
PromiseFlatString(aStatus).get());
}
NS_IMETHODIMP nsMsgProgress::SetStatusString(const nsAString& aStatus) {
return OnStatusChange(nullptr, nullptr, NS_OK,
PromiseFlatString(aStatus).get());
}
NS_IMETHODIMP nsMsgProgress::StartMeteors() { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHODIMP nsMsgProgress::StopMeteors() { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHODIMP nsMsgProgress::ShowProgress(int32_t percent) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgProgress::SetWrappedStatusFeedback(
nsIMsgStatusFeedback* aJSStatusFeedback) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgProgress::SetMsgWindow(nsIMsgWindow* aMsgWindow) {
m_msgWindow = do_GetWeakReference(aMsgWindow);
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::GetMsgWindow(nsIMsgWindow** aMsgWindow) {
NS_ENSURE_ARG_POINTER(aMsgWindow);
if (m_msgWindow)
CallQueryReferent(m_msgWindow.get(), aMsgWindow);
else
*aMsgWindow = nullptr;
return NS_OK;
}
NS_IMETHODIMP nsMsgProgress::OnProgress(nsIRequest* request, int64_t aProgress,
int64_t aProgressMax) {
// XXX: What should the nsIWebProgress be?
// XXX: This truncates 64-bit to 32-bit
return OnProgressChange(nullptr, request, int32_t(aProgress),
int32_t(aProgressMax),
int32_t(aProgress) /* current total progress */,
int32_t(aProgressMax) /* max total progress */);
}
NS_IMETHODIMP nsMsgProgress::OnStatus(nsIRequest* request, nsresult aStatus,
const char16_t* aStatusArg) {
nsresult rv;
nsCOMPtr<nsIStringBundleService> sbs =
mozilla::components::StringBundle::Service();
NS_ENSURE_TRUE(sbs, NS_ERROR_UNEXPECTED);
nsString str;
rv = sbs->FormatStatusMessage(aStatus, aStatusArg, str);
NS_ENSURE_SUCCESS(rv, rv);
return ShowStatusString(str);
}