diff options
Diffstat (limited to 'embed/mozilla/EphyDownload.cpp')
-rw-r--r-- | embed/mozilla/EphyDownload.cpp | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/embed/mozilla/EphyDownload.cpp b/embed/mozilla/EphyDownload.cpp new file mode 100644 index 000000000..062abc983 --- /dev/null +++ b/embed/mozilla/EphyDownload.cpp @@ -0,0 +1,470 @@ +/* -*- 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 "EphyDownload.h" + +#include "nsIExternalHelperAppService.h" +//#include "nsILocalFIleMac.h" +#include "nsDirectoryServiceDefs.h" +#include "nsDirectoryServiceUtils.h" +#include "nsIRequest.h" +#include "netCore.h" +#include "nsIObserver.h" + +//#include "UDownloadDisplay.h" +//#include "UMacUnicode.h" + +//#include "UNavServicesDialogs.h" + + +//***************************************************************************** +// EphyDownload +//***************************************************************************** +#pragma mark [EphyDownload] + +//ADownloadProgressView *EphyDownload::sProgressView; + +EphyDownload::EphyDownload() : + mGotFirstStateChange(false), mIsNetworkTransfer(false), + mUserCanceled(false), + mStatus(NS_OK) +{ +} + +EphyDownload::~EphyDownload() +{ +} + +NS_IMPL_ISUPPORTS2(EphyDownload, nsIDownload, nsIWebProgressListener) + +#pragma mark - +#pragma mark [EphyDownload::nsIDownload] + +/* void init (in nsIURI aSource, in nsILocalFile aTarget, in wstring aDisplayName, in nsIMIMEInfo aMIMEInfo, in long long startTime, in nsIWebBrowserPersist aPersist); */ +NS_IMETHODIMP +EphyDownload::Init(nsIURI *aSource, nsILocalFile *aTarget, const PRUnichar *aDisplayName, + nsIMIMEInfo *aMIMEInfo, PRInt64 startTime, nsIWebBrowserPersist *aPersist) +{ + try { + mSource = aSource; + mDestination = aTarget; + mStartTime = startTime; + mPercentComplete = 0; + mInterval = 400000; // ms + mPriorKRate = 0; + mRateChanges = 0; + mRateChangeLimit = 2; + mIsPaused = PR_FALSE; + mStartTime = PR_Now(); + mLastUpdate = mStartTime; + if (aPersist) { + mWebPersist = aPersist; + // We have to break this circular ref when the download is done - + // until nsIWebBrowserPersist supports weak refs - bug #163889. + aPersist->SetProgressListener(this); + } + // UI Rumba + mDownloaderView = EPHY_DOWNLOADER_VIEW (ephy_embed_shell_get_downloader_view + (embed_shell)); + downloader_view_add_download (mDownloaderView, "A", "B", "C", (gpointer)this); + // EnsureProgressView(); + // sProgressView->AddDownloadItem(this); + } + catch (...) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +/* readonly attribute nsIURI source; */ +NS_IMETHODIMP +EphyDownload::GetSource(nsIURI * *aSource) +{ + NS_ENSURE_ARG_POINTER(aSource); + NS_IF_ADDREF(*aSource = mSource); + return NS_OK; +} + +/* readonly attribute nsILocalFile target; */ +NS_IMETHODIMP +EphyDownload::GetTarget(nsILocalFile * *aTarget) +{ + NS_ENSURE_ARG_POINTER(aTarget); + NS_IF_ADDREF(*aTarget = mDestination); + return NS_OK; +} + +/* readonly attribute nsIWebBrowserPersist persist; */ +NS_IMETHODIMP +EphyDownload::GetPersist(nsIWebBrowserPersist * *aPersist) +{ + NS_ENSURE_ARG_POINTER(aPersist); + NS_IF_ADDREF(*aPersist = mWebPersist); + return NS_OK; +} + +/* readonly attribute PRInt32 percentComplete; */ +NS_IMETHODIMP +EphyDownload::GetPercentComplete(PRInt32 *aPercentComplete) +{ + NS_ENSURE_ARG_POINTER(aPercentComplete); + *aPercentComplete = mPercentComplete; + return NS_OK; +} + +/* attribute wstring displayName; */ +NS_IMETHODIMP +EphyDownload::GetDisplayName(PRUnichar * *aDisplayName) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +EphyDownload::SetDisplayName(const PRUnichar * aDisplayName) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* readonly attribute long long startTime; */ +NS_IMETHODIMP +EphyDownload::GetStartTime(PRInt64 *aStartTime) +{ + NS_ENSURE_ARG_POINTER(aStartTime); + *aStartTime = mStartTime; + return NS_OK; +} + +/* readonly attribute nsIMIMEInfo MIMEInfo; */ +NS_IMETHODIMP +EphyDownload::GetMIMEInfo(nsIMIMEInfo * *aMIMEInfo) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute nsIWebProgressListener listener; */ +NS_IMETHODIMP +EphyDownload::GetListener(nsIWebProgressListener * *aListener) +{ + NS_ENSURE_ARG_POINTER(aListener); + NS_IF_ADDREF(*aListener = (nsIWebProgressListener *)this); + return NS_OK; +} + +NS_IMETHODIMP +EphyDownload::SetListener(nsIWebProgressListener * aListener) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute nsIObserver observer; */ +NS_IMETHODIMP +EphyDownload::GetObserver(nsIObserver * *aObserver) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +EphyDownload::SetObserver(nsIObserver * aObserver) +{ + if (aObserver) + aObserver->QueryInterface(NS_GET_IID(nsIHelperAppLauncher), getter_AddRefs(mHelperAppLauncher)); + return NS_OK; +} + +#pragma mark - +#pragma mark [EphyDownload::nsIWebProgressListener] + +/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */ +NS_IMETHODIMP +EphyDownload::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))) { + if (mWebPersist) { + mWebPersist->SetProgressListener(nsnull); + mWebPersist = nsnull; + } + mHelperAppLauncher = 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 +EphyDownload::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, + PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, + PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) +{ + if (mUserCanceled) { + if (mHelperAppLauncher) + mHelperAppLauncher->Cancel(); + else if (aRequest) + aRequest->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); + // From ProgressListener + PRInt64 now = PR_Now(); + mElapsed = now - mStartTime; + + if ((now - mLastUpdate < mInterval) && + (aMaxTotalProgress != -1) && + (aCurTotalProgress < aMaxTotalProgress)) + { + return NS_OK; + } + mLastUpdate = now; + + + gfloat progress = -1; + if (aMaxTotalProgress > 0) + { + progress = (gfloat)aCurTotalProgress / + (gfloat)aMaxTotalProgress; + } + + /* compute download rate */ + gfloat speed = -1; + PRInt64 currentRate; + if (mElapsed) + { + currentRate = ((PRInt64)(aCurTotalProgress)) * 1000000 / mElapsed; + } + else + { + currentRate = 0; + } + + if (!mIsPaused && currentRate) + { + PRFloat64 currentKRate = ((PRFloat64)currentRate)/1024; + if (currentKRate != mPriorKRate) + { + if (mRateChanges++ == mRateChangeLimit) + { + mPriorKRate = currentKRate; + mRateChanges = 0; + } + else + { + currentKRate = mPriorKRate; + } + } + else + { + mRateChanges = 0; + } + + speed = currentKRate; + } + + /* compute time remaining */ + gint remaining = -1; + if (currentRate && (aMaxTotalProgress > 0)) + { + remaining = (gint)((aMaxTotalProgress - aCurTotalProgress) + /currentRate + 0.5); + } + + //BroadcastMessage(msg_OnDLProgressChange, &info); + // UI Rumba + downloader_view_set_download_progress (mDownloaderView, + mElapsed / 1000000, + remaining, + speed, + aMaxTotalProgress / 1024.0 + 0.5, + aCurTotalProgress / 1024.0 + 0.5, + progress, + (gpointer)this); + + return NS_OK; +} + +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ +NS_IMETHODIMP +EphyDownload::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 +EphyDownload::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 +EphyDownload::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) +{ + return NS_OK; +} + +#pragma mark - +#pragma mark [EphyDownload Internal Methods] + +void +EphyDownload::Cancel() +{ + mUserCanceled = true; + // nsWebBrowserPersist does the right thing: After canceling, next time through + // OnStateChange(), aStatus != NS_OK. This isn't the case with nsExternalHelperAppService. + if (!mWebPersist) + mStatus = NS_ERROR_ABORT; +} + +void +EphyDownload::Pause() +{ +} + +void +EphyDownload::Resume() +{ +} + +/*void +EphyDownload::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 boolean aForced); */ +/*NS_IMETHODIMP CHelperAppLauncherDialog::Show(nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRBool aForced) +{ + 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; +}*/ + |