aboutsummaryrefslogtreecommitdiffstats
path: root/embed/mozilla/EphyDownload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'embed/mozilla/EphyDownload.cpp')
-rw-r--r--embed/mozilla/EphyDownload.cpp470
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;
+}*/
+