mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 19:50:12 +01:00
322 lines
12 KiB
C++
322 lines
12 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 2002
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Conrad Carlen <ccarlen@netscape.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include "UDownload.h"
|
|
|
|
#include "nsIExternalHelperAppService.h"
|
|
#include "nsILocalFIleMac.h"
|
|
#include "nsDirectoryServiceDefs.h"
|
|
#include "nsDirectoryServiceUtils.h"
|
|
#include "nsIRequest.h"
|
|
#include "netCore.h"
|
|
|
|
#include "UDownloadDisplay.h"
|
|
#include "UMacUnicode.h"
|
|
|
|
#include "UNavServicesDialogs.h"
|
|
|
|
|
|
//*****************************************************************************
|
|
// CDownload
|
|
//*****************************************************************************
|
|
#pragma mark [CDownload]
|
|
|
|
ADownloadProgressView *CDownload::sProgressView;
|
|
|
|
CDownload::CDownload() :
|
|
mGotFirstStateChange(false), mIsNetworkTransfer(false),
|
|
mUserCanceled(false),
|
|
mStatus(NS_OK)
|
|
{
|
|
}
|
|
|
|
CDownload::~CDownload()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS4(CDownload, nsIDownload, nsITransfer,
|
|
nsIWebProgressListener, nsIWebProgressListener2)
|
|
|
|
#pragma mark -
|
|
#pragma mark [CDownload::nsIDownload]
|
|
|
|
/* void init (in nsIURI aSource, in nsILocalFile aTarget, in wstring aDisplayName, in nsIMIMEInfo aMIMEInfo, in long long startTime, in nsILocalFile aTempFile, in nsICancelable aCancelable); */
|
|
NS_IMETHODIMP CDownload::Init(nsIURI *aSource, nsILocalFile *aTarget,
|
|
const PRUnichar *aDisplayName, nsIMIMEInfo *aMIMEInfo, PRInt64 startTime,
|
|
nsILocalFile* aTempFile, nsICancelable* aCancelable)
|
|
{
|
|
try {
|
|
mSource = aSource;
|
|
mDestination = aTarget;
|
|
mStartTime = startTime;
|
|
mPercentComplete = 0;
|
|
// We have to break this circular ref when the download is done
|
|
mCancelable = aCancelable;
|
|
EnsureProgressView();
|
|
sProgressView->AddDownloadItem(this);
|
|
}
|
|
catch (...) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
/* readonly attribute nsIURI source; */
|
|
NS_IMETHODIMP CDownload::GetSource(nsIURI * *aSource)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_IF_ADDREF(*aSource = mSource);
|
|
return NS_OK;
|
|
}
|
|
|
|
/* readonly attribute nsILocalFile target; */
|
|
NS_IMETHODIMP CDownload::GetTarget(nsILocalFile * *aTarget)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aTarget);
|
|
NS_IF_ADDREF(*aTarget = mDestination);
|
|
return NS_OK;
|
|
}
|
|
|
|
/* readonly attribute nsICancelable cancelable; */
|
|
NS_IMETHODIMP CDownload::GetCancelable(nsIWebBrowserCancelable * *aCancelable)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aCancelable);
|
|
NS_IF_ADDREF(*aCancelable = mCancelable);
|
|
return NS_OK;
|
|
}
|
|
|
|
/* readonly attribute PRInt32 percentComplete; */
|
|
NS_IMETHODIMP CDownload::GetPercentComplete(PRInt32 *aPercentComplete)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aPercentComplete);
|
|
*aPercentComplete = mPercentComplete;
|
|
return NS_OK;
|
|
}
|
|
|
|
/* attribute wstring displayName; */
|
|
NS_IMETHODIMP CDownload::GetDisplayName(PRUnichar * *aDisplayName)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* readonly attribute long long startTime; */
|
|
NS_IMETHODIMP CDownload::GetStartTime(PRInt64 *aStartTime)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aStartTime);
|
|
*aStartTime = mStartTime;
|
|
return NS_OK;
|
|
}
|
|
|
|
/* readonly attribute nsIMIMEInfo MIMEInfo; */
|
|
NS_IMETHODIMP CDownload::GetMIMEInfo(nsIMIMEInfo * *aMIMEInfo)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark [CDownload::nsIWebProgressListener]
|
|
|
|
/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
|
|
NS_IMETHODIMP CDownload::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
|
|
{
|
|
// For a file download via the external helper app service, we will never get a start
|
|
// notification. The helper app service has gotten that notification before it created us.
|
|
if (!mGotFirstStateChange) {
|
|
mIsNetworkTransfer = ((aStateFlags & STATE_IS_NETWORK) != 0);
|
|
mGotFirstStateChange = PR_TRUE;
|
|
BroadcastMessage(msg_OnDLStart, this);
|
|
}
|
|
|
|
if (NS_FAILED(aStatus) && NS_SUCCEEDED(mStatus))
|
|
mStatus = aStatus;
|
|
|
|
// We will get this even in the event of a cancel,
|
|
if ((aStateFlags & STATE_STOP) && (!mIsNetworkTransfer || (aStateFlags & STATE_IS_NETWORK))) {
|
|
mCancelable = nsnull;
|
|
BroadcastMessage(msg_OnDLComplete, this);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
|
|
NS_IMETHODIMP CDownload::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
|
|
{
|
|
if (mUserCanceled) {
|
|
mCancelable->Cancel(NS_BINDING_ABORTED);
|
|
mUserCanceled = false;
|
|
}
|
|
if (aMaxTotalProgress == -1)
|
|
mPercentComplete = -1;
|
|
else
|
|
mPercentComplete = (PRInt32)(((float)aCurTotalProgress / (float)aMaxTotalProgress) * 100.0 + 0.5);
|
|
|
|
MsgOnDLProgressChangeInfo info(this, aCurTotalProgress, aMaxTotalProgress);
|
|
BroadcastMessage(msg_OnDLProgressChange, &info);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/* void onProgressChange64 (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long long aCurSelfProgress, in long long aMaxSelfProgress, in long long aCurTotalProgress, in long long aMaxTotalProgress); */
|
|
NS_IMETHODIMP CDownload::OnProgressChange64(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt64 aCurSelfProgress, PRInt64 aMaxSelfProgress, PRInt64 aCurTotalProgress, PRInt64 aMaxTotalProgress)
|
|
{
|
|
// XXX truncates 64-bit to 32-bit
|
|
return OnProgressChange(aProgress, aRequest,
|
|
PRInt32(curSelfProgress), PRInt32(maxSelfProgress),
|
|
PRInt32(curTotalProgress), PRInt32(maxTotalProgress));
|
|
}
|
|
|
|
|
|
/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
|
|
NS_IMETHODIMP CDownload::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
|
|
NS_IMETHODIMP CDownload::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
|
|
NS_IMETHODIMP CDownload::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark [CDownload Internal Methods]
|
|
|
|
void CDownload::Cancel()
|
|
{
|
|
mUserCanceled = true;
|
|
// nsWebBrowserPersist does the right thing: After canceling, next time through
|
|
// OnStateChange(), aStatus != NS_OK. This isn't the case with nsExternalHelperAppService.
|
|
mStatus = NS_ERROR_ABORT;
|
|
}
|
|
|
|
void CDownload::CreateProgressView()
|
|
{
|
|
sProgressView = new CMultiDownloadProgress;
|
|
ThrowIfNil_(sProgressView);
|
|
}
|
|
|
|
|
|
//*****************************************************************************
|
|
// CHelperAppLauncherDialog
|
|
//*****************************************************************************
|
|
#pragma mark -
|
|
#pragma mark [CHelperAppLauncherDialog]
|
|
|
|
CHelperAppLauncherDialog::CHelperAppLauncherDialog()
|
|
{
|
|
}
|
|
|
|
CHelperAppLauncherDialog::~CHelperAppLauncherDialog()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS1(CHelperAppLauncherDialog, nsIHelperAppLauncherDialog)
|
|
|
|
/* void show (in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in unsigned long aReason); */
|
|
NS_IMETHODIMP CHelperAppLauncherDialog::Show(nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRUint32 aReason)
|
|
{
|
|
return aLauncher->SaveToDisk(nsnull, PR_FALSE);
|
|
}
|
|
|
|
/* nsILocalFile promptForSaveToFile (in nsIHelperAppLauncher aLauncher, in nsISupports aWindowContext, in wstring aDefaultFile, in wstring aSuggestedFileExtension); */
|
|
NS_IMETHODIMP CHelperAppLauncherDialog::PromptForSaveToFile(nsIHelperAppLauncher* aLauncher,
|
|
nsISupports *aWindowContext,
|
|
const PRUnichar *aDefaultFile,
|
|
const PRUnichar *aSuggestedFileExtension,
|
|
nsILocalFile **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
|
|
static bool sFirstTime = true;
|
|
UNavServicesDialogs::LFileDesignator designator;
|
|
|
|
if (sFirstTime) {
|
|
// Get the default download folder and point Nav Sevices to it.
|
|
nsCOMPtr<nsIFile> defaultDownloadDir;
|
|
NS_GetSpecialDirectory(NS_MAC_DEFAULT_DOWNLOAD_DIR, getter_AddRefs(defaultDownloadDir));
|
|
if (defaultDownloadDir) {
|
|
nsCOMPtr<nsILocalFileMac> macDir(do_QueryInterface(defaultDownloadDir));
|
|
FSSpec defaultDownloadSpec;
|
|
if (NS_SUCCEEDED(macDir->GetFSSpec(&defaultDownloadSpec)))
|
|
designator.SetDefaultLocation(defaultDownloadSpec, true);
|
|
}
|
|
sFirstTime = false;
|
|
}
|
|
|
|
Str255 defaultName;
|
|
CPlatformUCSConversion::GetInstance()->UCSToPlatform(nsDependentString(aDefaultFile), defaultName);
|
|
bool result = designator.AskDesignateFile(defaultName);
|
|
|
|
// After the dialog is dismissed, process all activation an update events right away.
|
|
// The save dialog code calls UDesktop::Activate after dismissing the dialog. All that
|
|
// does is activate the now frontmost LWindow which was behind the dialog. It does not
|
|
// remove the activate event from the queue. If that event is not processed and removed
|
|
// before we show the progress window, bad things happen. Specifically, the progress
|
|
// dialog will show in front and then, shortly thereafter, the window which was behind this save
|
|
// dialog will be moved to the front.
|
|
|
|
if (LEventDispatcher::GetCurrentEventDispatcher()) { // Can this ever be NULL?
|
|
EventRecord theEvent;
|
|
while (::WaitNextEvent(updateMask | activMask, &theEvent, 0, nil))
|
|
LEventDispatcher::GetCurrentEventDispatcher()->DispatchEvent(theEvent);
|
|
}
|
|
|
|
if (result) {
|
|
FSSpec destSpec;
|
|
designator.GetFileSpec(destSpec);
|
|
nsCOMPtr<nsILocalFileMac> destFile;
|
|
NS_NewLocalFileWithFSSpec(&destSpec, PR_TRUE, getter_AddRefs(destFile));
|
|
if (!destFile)
|
|
return NS_ERROR_FAILURE;
|
|
*_retval = destFile;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
else
|
|
return NS_ERROR_ABORT;
|
|
}
|
|
|