diff options
Diffstat (limited to 'embed/mozilla/ProgressListener.cpp')
-rw-r--r-- | embed/mozilla/ProgressListener.cpp | 718 |
1 files changed, 718 insertions, 0 deletions
diff --git a/embed/mozilla/ProgressListener.cpp b/embed/mozilla/ProgressListener.cpp new file mode 100644 index 000000000..aed42d97a --- /dev/null +++ b/embed/mozilla/ProgressListener.cpp @@ -0,0 +1,718 @@ +/* + * Copyright (C) 2001 Philip Langdale, Matthew Aubury + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "ProgressListener.h" + +#include "eel-gconf-extensions.h" +#include "ephy-file-helpers.h" + +#include <unistd.h> +#include <libgnome/gnome-exec.h> +#include <libgnome/gnome-i18n.h> + +#include "nsXPIDLString.h" +#include "nsIChannel.h" +#include "nsIFTPChannel.h" +#include "nsIFactory.h" +#include "nsXPComFactory.h" +#include "nsIMIMEInfo.h" +#include "nsCOMPtr.h" + +static void +download_remove_cb (DownloaderView *dv, GProgressListener *Progress); +static void +download_resume_cb (DownloaderView *dv, GProgressListener *Progress); +static void +download_pause_cb (DownloaderView *dv, GProgressListener *Progress); + +NS_IMPL_ISUPPORTS4 (GProgressListener, nsIDownload, nsIWebProgressListener, + nsIProgressDialog, nsISupportsWeakReference) + +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- + +GProgressListener::GProgressListener () : mLauncher(nsnull), + mPersist(nsnull), + mHandler(nsnull), + mObserver(nsnull), + mMIMEInfo(nsnull), + mPercentComplete(0) +{ + NS_INIT_ISUPPORTS (); +} + +GProgressListener::~GProgressListener () +{ + /* destructor code */ +} + +NS_METHOD GProgressListener::InitForPersist (nsIWebBrowserPersist *aPersist, + nsIDOMWindow *aParent, + nsIURI *aURI, + nsIFile *aFile, + DownloadAction aAction, + EphyEmbedPersist *ephyPersist, + PRBool noDialog, + PRInt64 aTimeDownloadStarted) +{ + nsresult rv; + + /* fill in download details */ + mAction = aAction; + mParent = aParent; + mNoDialog = noDialog; + mUri = aURI; + mFile = aFile; + mPersist = aPersist; + mTimeDownloadStarted = aTimeDownloadStarted; + mEphyPersist = ephyPersist; + + /* do remaining init */ + rv = PrivateInit (); + + /* pick up progress messages */ + mPersist->SetProgressListener (this); + + /* done */ + return rv; +} + +NS_METHOD GProgressListener::InitForDownload (nsIHelperAppLauncher *aLauncher, + nsISupports *aContext, + GContentHandler *aHandler, + DownloadAction aAction) +{ + nsresult rv; + + mNoDialog = 0; + + /* fill in download details */ + mAction = aAction; + mParent = do_QueryInterface (aContext); + mNoDialog = PR_TRUE; + mHandler = aHandler; + mLauncher = aLauncher; + rv = mLauncher->GetDownloadInfo (getter_AddRefs (mUri), + &mTimeDownloadStarted, + getter_AddRefs (mFile)); + + /* do remaining init */ + rv = PrivateInit (); + + /* pick up progress messages */ + mLauncher->SetWebProgressListener (this); + + /* done */ + return rv; +} + +NS_METHOD GProgressListener::PrivateInit (void) +{ + nsresult rv; + + /* setup this download */ + mInterval = 500000; /* in microsecs == 500ms == 0.5s */ + mPriorKRate = 0; + mRateChanges = 0; + mRateChangeLimit = 2; /* only update rate every second */ + mCheckedCanPause = PR_FALSE; + mCanPause = PR_FALSE; + mIsPaused = PR_FALSE; + mAbort = PR_FALSE; + PRInt64 now = PR_Now (); + mLastUpdate = now; + +// mStartTime = (mTimeDownloadStarted != 0 ? +// mTimeDownloadStarted : now); + mStartTime = now; //Stupid mozilla race condition + + mElapsed = now - mStartTime; + + if (!mNoDialog) + { + gchar *filename, *source, *dest; + nsAutoString uTmp; + nsCAutoString cTmp; + + rv = mFile->GetLeafName (uTmp); + filename = g_strdup (NS_ConvertUCS2toUTF8(uTmp).get()); + + rv = mFile->GetPath (uTmp); + dest = g_strdup (NS_ConvertUCS2toUTF8(uTmp).get()); + + rv = mUri->GetSpec (cTmp); + source = g_strdup (cTmp.get()); + DownloaderView *dv; + dv = ephy_embed_shell_get_downloader_view (embed_shell); + downloader_view_add_download (dv, filename, source, dest, (gpointer)this); + g_signal_connect (G_OBJECT (dv), + "download_remove", + G_CALLBACK (download_remove_cb), + this); + g_signal_connect (G_OBJECT (dv), + "download_pause", + G_CALLBACK (download_pause_cb), + this); + g_signal_connect (G_OBJECT (dv), + "download_resume", + G_CALLBACK (download_resume_cb), + this); + mDownloaderView = dv; + } + + /* done */ + return NS_OK; +} + +NS_IMETHODIMP GProgressListener::Init(nsIURI *aSource, + nsILocalFile *aTarget, + const PRUnichar *aDisplayName, + nsIMIMEInfo *aMIMEInfo, + PRInt64 aStartTime, + nsIWebBrowserPersist *aPersist) +{ + mUri = aSource; + mFile = aTarget; + mTimeDownloadStarted = aStartTime; + mStartTime = aStartTime; + mPersist = aPersist; + mMIMEInfo = aMIMEInfo; + mAction = ACTION_NONE; + if(mMIMEInfo) + { + nsMIMEInfoHandleAction mimeAction; + if(NS_SUCCEEDED(mMIMEInfo->GetPreferredAction(&mimeAction))) + { + mAction = (mimeAction == nsIMIMEInfo::useHelperApp) ? + ACTION_SAVEFORHELPER : ACTION_NONE; + } + } + mNoDialog = 0; + + return PrivateInit(); +} + +NS_IMETHODIMP GProgressListener::Open(nsIDOMWindow *aParent) +{ + mParent = aParent; + mNoDialog = 0; + + return NS_OK; +} + +/* attribute long long startTime; */ +NS_IMETHODIMP GProgressListener::GetStartTime(PRInt64 *aStartTime) +{ + *aStartTime = mStartTime; + return NS_OK; +} + +/* attribute nsIURI source; */ +NS_IMETHODIMP GProgressListener::GetSource(nsIURI * *aSource) +{ + NS_IF_ADDREF(*aSource = mUri); + return NS_OK; +} + +/* attribute nsILocalFile target; */ +NS_IMETHODIMP GProgressListener::GetTarget(nsILocalFile * *aTarget) +{ + nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(mFile); + NS_IF_ADDREF(*aTarget = localFile); + return NS_OK; +} + +NS_IMETHODIMP GProgressListener::GetMIMEInfo(nsIMIMEInfo * *aMIMEInfo) +{ + NS_IF_ADDREF(*aMIMEInfo = mMIMEInfo); + return NS_OK; +} + +/* attribute nsIObserver observer; */ +NS_IMETHODIMP GProgressListener::GetObserver(nsIObserver * *aObserver) +{ + NS_IF_ADDREF(*aObserver = mObserver); + return NS_OK; +} +NS_IMETHODIMP GProgressListener::SetObserver(nsIObserver * aObserver) +{ + mObserver = aObserver; + return NS_OK; +} + +/* attribute nsIWebProgressListener listener; */ +NS_IMETHODIMP GProgressListener::GetListener(nsIWebProgressListener * *aListener) +{ + *aListener = nsnull; + return NS_OK; +} +NS_IMETHODIMP GProgressListener::SetListener(nsIWebProgressListener * aListener) +{ + return NS_OK; +} + +/* readonly attribute PRInt32 percentComplete; */ +NS_IMETHODIMP GProgressListener::GetPercentComplete(PRInt32 *aPercentComplete) +{ + return *aPercentComplete = mPercentComplete; +} + +/* attribute wstring displayName; */ +NS_IMETHODIMP GProgressListener::GetDisplayName(PRUnichar * *aDisplayName) +{ + *aDisplayName = nsnull; + return NS_OK; +} +NS_IMETHODIMP GProgressListener::SetDisplayName(const PRUnichar * aDisplayName) +{ + return NS_OK; +} + +NS_IMETHODIMP GProgressListener::GetPersist(nsIWebBrowserPersist * *aPersist) +{ + NS_IF_ADDREF(*aPersist = mPersist); + return NS_OK; +} + +NS_IMETHODIMP GProgressListener::SetDialog(nsIDOMWindow *aDialog) +{ + return NS_OK; +} + +NS_IMETHODIMP GProgressListener::GetDialog(nsIDOMWindow * *aDialog) +{ + *aDialog = nsnull; + return NS_OK; +} + +/* attribute PRBool cancelDownloadOnClose; */ +NS_IMETHODIMP GProgressListener::GetCancelDownloadOnClose(PRBool *aCancelDownloadOnClose) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP GProgressListener::SetCancelDownloadOnClose(PRBool aCancelDownloadOnClose) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP GProgressListener::LaunchHandler (PersistHandlerInfo *handler) +{ + nsresult rv; + nsCOMPtr<nsIExternalHelperAppService> helperService = + do_GetService (NS_EXTERNALHELPERAPPSERVICE_CONTRACTID); + + nsCOMPtr<nsPIExternalAppLauncher> appLauncher = + do_QueryInterface (helperService, &rv); + if (NS_SUCCEEDED(rv)) + { + appLauncher->DeleteTemporaryFileOnExit(mFile); + } + + nsAutoString uFileName; + + mFile->GetPath(uFileName); + const nsACString &cFileName = NS_ConvertUCS2toUTF8(uFileName); + + char *fname = g_strdup(PromiseFlatCString(cFileName).get()); + ephy_file_launch_application (handler->command, + fname, + handler->need_terminal); + g_free (fname); + + return NS_OK; +} + +/* + * void onStateChange (in nsIWebProgress aWebProgress, + * in nsIRequest aRequest, + * in long aStateFlags, + * in unsigned long aStatus); + */ +NS_IMETHODIMP GProgressListener::OnStateChange (nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRUint32 aStateFlags, + PRUint32 aStatus) +{ + if (mAbort) return NS_ERROR_FAILURE; + + if (aStateFlags & nsIWebProgressListener::STATE_STOP) + { + switch (mAction) + { + case ACTION_SAVEFORHELPER: + LaunchHelperApp(); + break; + + case ACTION_NONE: + if (mLauncher) + { + mLauncher->CloseProgressWindow (); + } + break; + case ACTION_OBJECT_NOTIFY: + + g_return_val_if_fail (IS_EPHY_EMBED_PERSIST (mEphyPersist), + NS_ERROR_FAILURE); + + PersistHandlerInfo *handler; + + g_object_get (mEphyPersist, + "handler", &handler, + NULL); + + if (handler) + { + LaunchHandler (handler); + } + + g_signal_emit_by_name (mEphyPersist, "completed"); + } + + if (!mNoDialog) + { + downloader_view_set_download_status (mDownloaderView, + DOWNLOAD_STATUS_COMPLETED, + (gpointer)this); + } + } + + /* done */ + 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 GProgressListener:: + OnProgressChange (nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRInt32 aCurSelfProgress, + PRInt32 aMaxSelfProgress, + PRInt32 aCurTotalProgress, + PRInt32 aMaxTotalProgress) +{ + if (mAbort) return NS_ERROR_FAILURE; + + /* FIXME maxsize check here */ + + if (mNoDialog) return NS_OK; + + if (!mCheckedCanPause) + { + mCheckedCanPause = PR_TRUE; + + nsresult rv; + nsCOMPtr<nsIFTPChannel> channel = + do_QueryInterface (aRequest, &rv); + + mCanPause = (NS_SUCCEEDED (rv) ? PR_TRUE : PR_FALSE); + } + mRequest = aRequest; + + PRInt64 now = PR_Now (); + + /* get out if we're updating too quickly */ + if ((now - mLastUpdate < mInterval) && + (aMaxTotalProgress != -1) && + (aCurTotalProgress < aMaxTotalProgress)) + { + return NS_OK; + } + + /* compute elapsed time */ + mLastUpdate = now; + mElapsed = now - mStartTime; + + /* compute size done */ + PRInt32 currentKBytes = (PRInt32)(aCurTotalProgress / 1024.0 + 0.5); + + /* compute total size */ + PRInt32 totalKBytes = (PRInt32)(aMaxTotalProgress / 1024.0 + 0.5); + + /* compute progress value */ + 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) + { + if (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 +.5); + } + + downloader_view_set_download_progress (mDownloaderView, + mElapsed, + remaining, + speed, + totalKBytes, + currentKBytes, + progress, + mCanPause, + (gpointer)this); + + /* done */ + return NS_OK; +} + +/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ +NS_IMETHODIMP GProgressListener:: + 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 GProgressListener:: + OnStatusChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, nsresult aStatus, + const PRUnichar *aMessage) +{ + return NS_OK; +} + +/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */ +NS_IMETHODIMP GProgressListener:: + OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRUint32 state) +{ + return NS_OK; +} + +//--------------------------------------------------------------------------- + +NS_METHOD GProgressListener::LaunchHelperApp (void) +{ + if (!mMIMEInfo) + return NS_ERROR_FAILURE; + + nsresult rv; + + nsCOMPtr<nsIFile> helperFile; + rv = mMIMEInfo->GetPreferredApplicationHandler(getter_AddRefs(helperFile)); + if(NS_FAILED(rv)) return NS_ERROR_FAILURE; + + nsCAutoString helperFileName; + rv = helperFile->GetNativePath(helperFileName); + if(NS_FAILED(rv)) return NS_ERROR_FAILURE; + + nsMIMEInfoHandleAction mimeAction; + rv = mMIMEInfo->GetPreferredAction(&mimeAction); + if(NS_FAILED(rv)) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIExternalHelperAppService> helperService = + do_GetService (NS_EXTERNALHELPERAPPSERVICE_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr<nsPIExternalAppLauncher> appLauncher = + do_QueryInterface (helperService, &rv); + if (NS_SUCCEEDED(rv)) + { + appLauncher->DeleteTemporaryFileOnExit(mFile); + } + } + + nsCAutoString cFileName; + mFile->GetNativePath(cFileName); + if(NS_FAILED(rv)) return NS_ERROR_FAILURE; + + nsXPIDLString helperDesc; + rv = mMIMEInfo->GetApplicationDescription(getter_Copies(helperDesc)); + if(NS_FAILED(rv)) return NS_ERROR_FAILURE; + + gboolean terminalHelper = + helperDesc.Equals(NS_LITERAL_STRING("runInTerminal")) ? + TRUE : FALSE; + + ephy_file_launch_application (helperFileName.get(), + cFileName.get(), + terminalHelper); + + return NS_OK; +} + +nsresult GProgressListener::Pause (void) +{ + nsresult rv; + + if (mCanPause && !mIsPaused) + { + rv = mRequest->Suspend (); + if (NS_SUCCEEDED (rv)) + { + mIsPaused = PR_TRUE; + } + } + else + { + rv = NS_ERROR_FAILURE; + } + + return rv; +} + +nsresult GProgressListener::Resume (void) +{ + nsresult rv; + + if (mCanPause && mIsPaused) + { + rv = mRequest->Resume (); + if (NS_SUCCEEDED (rv)) + { + mIsPaused = PR_FALSE; + } + } + else + { + rv = NS_ERROR_FAILURE; + } + + return rv; +} + +nsresult GProgressListener::Abort (void) +{ + mAction = ACTION_NONE; + + if (mIsPaused) + { + Resume (); + } + + mAbort = PR_TRUE; + + if (mObserver) + { + mObserver->Observe(NS_ISUPPORTS_CAST(nsIProgressDialog*, this), + "oncancel", nsnull); + OnStateChange(nsnull, nsnull, + nsIWebProgressListener::STATE_STOP, 0); + } + + if (mPersist) + { + return mPersist->CancelSave (); + } + + if (mLauncher) + { + return mLauncher->Cancel (); + } + else + { + return NS_ERROR_FAILURE; + } +} + +NS_DEF_FACTORY (GProgressListener, GProgressListener); + +/** + * NS_NewProgressListenerFactory: + */ +nsresult NS_NewProgressListenerFactory(nsIFactory** aFactory) +{ + NS_ENSURE_ARG_POINTER(aFactory); + *aFactory = nsnull; + + nsGProgressListenerFactory *result = new nsGProgressListenerFactory; + if (result == NULL) + { + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(result); + *aFactory = result; + + return NS_OK; +} + +static void +download_remove_cb (DownloaderView *dv, GProgressListener *Progress) +{ + Progress->Abort(); +} + +static void +download_resume_cb (DownloaderView *dv, GProgressListener *Progress) +{ + Progress->Resume(); +} + +static void +download_pause_cb (DownloaderView *dv, GProgressListener *Progress) +{ + Progress->Pause(); +} |