mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 245725 Make downloads display an approximation to the current transfer rate rather than the overall average speed p=son.le0@gmail.com r=biesi sr=me
This commit is contained in:
parent
f280152c5c
commit
5417075f05
@ -180,6 +180,13 @@ nsDownloadListener::GetStartTime(PRInt64 *aStartTime)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute double speed; */
|
||||
NS_IMETHODIMP
|
||||
nsDownloadListener::GetSpeed(double* aSpeed)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIMIMEInfo MIMEInfo; */
|
||||
NS_IMETHODIMP
|
||||
nsDownloadListener::GetMIMEInfo(nsIMIMEInfo * *aMIMEInfo)
|
||||
|
@ -151,6 +151,13 @@ nsDownloadListener::GetStartTime(PRInt64 *aStartTime)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute double speed; */
|
||||
NS_IMETHODIMP
|
||||
nsDownloadListener::GetSpeed(double* aSpeed)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIMIMEInfo MIMEInfo; */
|
||||
NS_IMETHODIMP
|
||||
nsDownloadListener::GetMIMEInfo(nsIMIMEInfo * *aMIMEInfo)
|
||||
|
@ -142,6 +142,12 @@ NS_IMETHODIMP CDownload::GetStartTime(PRInt64 *aStartTime)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute double speed; */
|
||||
NS_IMETHODIMP CDownload::GetSpeed(double *aSpeed)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIMIMEInfo MIMEInfo; */
|
||||
NS_IMETHODIMP CDownload::GetMIMEInfo(nsIMIMEInfo * *aMIMEInfo)
|
||||
{
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsIFileURL.h"
|
||||
#include "nsEmbedCID.h"
|
||||
#include "nsInt64.h"
|
||||
|
||||
/* Outstanding issues/todo:
|
||||
* 1. Implement pause/resume.
|
||||
@ -85,7 +86,8 @@ static PRBool gStoppingDownloads = PR_FALSE;
|
||||
#define PREF_BDM_FOCUSWHENSTARTING "browser.download.manager.focusWhenStarting"
|
||||
#define PREF_BDM_CLOSEWHENDONE "browser.download.manager.closeWhenDone"
|
||||
#define PREF_BDM_FLASHCOUNT "browser.download.manager.flashCount"
|
||||
#define INTERVAL 500
|
||||
|
||||
static const nsInt64 gInterval((PRUint32)(400 * PR_USEC_PER_MSEC));
|
||||
|
||||
static nsIRDFResource* gNC_DownloadsRoot = nsnull;
|
||||
static nsIRDFResource* gNC_File = nsnull;
|
||||
@ -1806,10 +1808,11 @@ NS_IMPL_ISUPPORTS4(nsDownload, nsIDownload, nsITransfer, nsIWebProgressListener,
|
||||
|
||||
nsDownload::nsDownload():mDownloadState(nsIDownloadManager::DOWNLOAD_NOTSTARTED),
|
||||
mPercentComplete(0),
|
||||
mCurrBytes(0),
|
||||
mMaxBytes(0),
|
||||
mStartTime(0),
|
||||
mLastUpdate(-500)
|
||||
mCurrBytes(LL_ZERO),
|
||||
mMaxBytes(LL_ZERO),
|
||||
mStartTime(LL_ZERO),
|
||||
mSpeed(0),
|
||||
mLastUpdate(PR_Now() - (PRUint32)gInterval)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1947,6 +1950,7 @@ nsresult
|
||||
nsDownload::SetStartTime(PRInt64 aStartTime)
|
||||
{
|
||||
mStartTime = aStartTime;
|
||||
mLastUpdate = aStartTime;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1972,10 +1976,9 @@ nsDownload::OnProgressChange64(nsIWebProgress *aWebProgress,
|
||||
mRequest = aRequest; // used for pause/resume
|
||||
|
||||
// filter notifications since they come in so frequently
|
||||
PRTime delta;
|
||||
PRTime now = PR_Now();
|
||||
LL_SUB(delta, now, mLastUpdate);
|
||||
if (LL_CMP(delta, <, INTERVAL) && aMaxTotalProgress != -1 && aCurTotalProgress < aMaxTotalProgress)
|
||||
nsInt64 delta = now - mLastUpdate;
|
||||
if (delta < gInterval)
|
||||
return NS_OK;
|
||||
|
||||
mLastUpdate = now;
|
||||
@ -1989,6 +1992,21 @@ nsDownload::OnProgressChange64(nsIWebProgress *aWebProgress,
|
||||
mDownloadManager->DownloadStarted(path.get());
|
||||
}
|
||||
|
||||
// Calculate the speed using the elapsed delta time and bytes downloaded
|
||||
// during that time for more accuracy.
|
||||
double elapsedSecs = double(delta) / PR_USEC_PER_SEC;
|
||||
if (elapsedSecs > 0) {
|
||||
nsUint64 curTotalProgress = (PRUint64)aCurTotalProgress;
|
||||
nsUint64 diffBytes = curTotalProgress - nsUint64(mCurrBytes);
|
||||
double speed = double(diffBytes) / elapsedSecs;
|
||||
if (LL_IS_ZERO(mCurrBytes))
|
||||
mSpeed = speed;
|
||||
else {
|
||||
// Calculate 'smoothed average' of 10 readings.
|
||||
mSpeed = mSpeed * 0.9 + speed * 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
if (aMaxTotalProgress > 0)
|
||||
mPercentComplete = (PRInt32)((PRFloat64)aCurTotalProgress * 100 / aMaxTotalProgress + .5);
|
||||
else
|
||||
@ -2077,8 +2095,9 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest, PRUint32 aStateFlags,
|
||||
nsresult aStatus)
|
||||
{
|
||||
if (aStateFlags & STATE_START)
|
||||
mStartTime = PR_Now();
|
||||
// Record the start time only if it hasn't been set.
|
||||
if (LL_IS_ZERO(mStartTime) && (aStateFlags & STATE_START))
|
||||
SetStartTime(PR_Now());
|
||||
|
||||
// When we break the ref cycle with mCancelable, we don't want to lose
|
||||
// access to out member vars!
|
||||
@ -2096,7 +2115,7 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
|
||||
else
|
||||
mDownloadState = nsIXPInstallManagerUI::INSTALL_FINISHED;
|
||||
|
||||
// Set file size at the end of a tranfer (for unknown transfer amounts)
|
||||
// Set file size at the end of a tranfer (for unknown transfer amounts)
|
||||
if (mMaxBytes == -1)
|
||||
mMaxBytes = mCurrBytes;
|
||||
|
||||
@ -2286,6 +2305,13 @@ nsDownload::GetTargetFile(nsILocalFile** aTargetFile)
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownload::GetSpeed(double* aSpeed)
|
||||
{
|
||||
*aSpeed = mSpeed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDownload::Pause(PRBool aPaused)
|
||||
{
|
||||
|
@ -259,8 +259,9 @@ private:
|
||||
PRInt32 mPercentComplete;
|
||||
PRUint64 mCurrBytes;
|
||||
PRUint64 mMaxBytes;
|
||||
PRInt64 mStartTime;
|
||||
PRTime mStartTime;
|
||||
PRTime mLastUpdate;
|
||||
double mSpeed;
|
||||
|
||||
friend class nsDownloadManager;
|
||||
};
|
||||
|
@ -154,6 +154,11 @@ public:
|
||||
return mInner->GetTargetFile(aTargetFile);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GetSpeed(double* aSpeed)
|
||||
{
|
||||
return mInner->GetSpeed(aSpeed);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP OnStateChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest, PRUint32 aStateFlags,
|
||||
PRUint32 aStatus)
|
||||
|
@ -59,7 +59,6 @@ function DownloadProgressListener (aDocument, aStringBundle)
|
||||
|
||||
DownloadProgressListener.prototype =
|
||||
{
|
||||
elapsed: 0,
|
||||
rateChanges: 0,
|
||||
rateChangeLimit: 0,
|
||||
priorRate: 0,
|
||||
@ -91,14 +90,6 @@ DownloadProgressListener.prototype =
|
||||
// Update this time.
|
||||
this.lastUpdate = now;
|
||||
|
||||
// Update download rate.
|
||||
this.elapsed = now - (aDownload.startTime / 1000);
|
||||
var rate; // aCurTotalProgress/sec
|
||||
if (this.elapsed)
|
||||
rate = (aCurTotalProgress * 1024) / this.elapsed;
|
||||
else
|
||||
rate = 0;
|
||||
|
||||
var aDownloadID = aDownload.targetFile.path;
|
||||
var download = this.doc.getElementById(aDownloadID);
|
||||
|
||||
@ -138,6 +129,7 @@ DownloadProgressListener.prototype =
|
||||
if (download)
|
||||
download.setAttribute("status-internal", kbProgress);
|
||||
|
||||
var rate = aDownload.speed;
|
||||
if (rate) {
|
||||
// rate is bytes/sec
|
||||
var kRate = rate / 1024; // K bytes/sec;
|
||||
@ -157,13 +149,13 @@ DownloadProgressListener.prototype =
|
||||
else
|
||||
this.rateChanges = 0;
|
||||
|
||||
var fraction = kRate % 10;
|
||||
kRate = parseInt((kRate - fraction) / 10);
|
||||
var fraction = kRate % 10;
|
||||
kRate = parseInt((kRate - fraction) / 10);
|
||||
|
||||
// Insert 3 is the download rate (in kilobytes/sec).
|
||||
if (kRate < 100)
|
||||
kRate += "." + fraction;
|
||||
status = this._replaceInsert(status, 2, kRate);
|
||||
// Insert 3 is the download rate (in kilobytes/sec).
|
||||
if (kRate < 100)
|
||||
kRate += "." + fraction;
|
||||
status = this._replaceInsert(status, 2, kRate);
|
||||
}
|
||||
else
|
||||
status = this._replaceInsert(status, 2, "??.?");
|
||||
|
@ -45,7 +45,7 @@ interface nsICancelable;
|
||||
interface nsIWebProgressListener;
|
||||
interface nsIMIMEInfo;
|
||||
|
||||
[scriptable, uuid(a60c9199-2e21-434f-a43b-ab954ea2f6b7)]
|
||||
[scriptable, uuid(07910093-d70b-4621-9888-b811f42293c3)]
|
||||
interface nsIDownload : nsITransfer {
|
||||
|
||||
/**
|
||||
@ -95,7 +95,12 @@ interface nsIDownload : nsITransfer {
|
||||
* The time a transfer was started.
|
||||
*/
|
||||
readonly attribute long long startTime;
|
||||
|
||||
|
||||
/**
|
||||
* The speed of the transfer in bytes/sec.
|
||||
*/
|
||||
readonly attribute double speed;
|
||||
|
||||
/**
|
||||
* Optional. If set, it will contain the target's relevant MIME information.
|
||||
* This includes it's MIME Type, helper app, and whether that helper should be
|
||||
|
@ -1602,6 +1602,10 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest *request, nsISuppo
|
||||
{
|
||||
NS_PRECONDITION(request, "OnStartRequest without request?");
|
||||
|
||||
// Set mTimeDownloadStarted here as the download has already started and
|
||||
// we want to record the start time before showing the filepicker.
|
||||
mTimeDownloadStarted = PR_Now();
|
||||
|
||||
mRequest = request;
|
||||
|
||||
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
|
||||
@ -1685,8 +1689,6 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest *request, nsISuppo
|
||||
encChannel->SetApplyConversion( applyConversion );
|
||||
}
|
||||
|
||||
mTimeDownloadStarted = PR_Now();
|
||||
|
||||
// now that the temp file is set up, find out if we need to invoke a dialog
|
||||
// asking the user what they want us to do with this content...
|
||||
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "nsIAlertsService.h"
|
||||
#endif
|
||||
#include "nsEmbedCID.h"
|
||||
#include "nsInt64.h"
|
||||
|
||||
/* Outstanding issues/todo:
|
||||
* 1. Implement pause/resume.
|
||||
@ -73,7 +74,8 @@
|
||||
|
||||
#define DOWNLOAD_MANAGER_FE_URL "chrome://communicator/content/downloadmanager/downloadmanager.xul"
|
||||
#define DOWNLOAD_MANAGER_BUNDLE "chrome://communicator/locale/downloadmanager/downloadmanager.properties"
|
||||
#define INTERVAL 500
|
||||
|
||||
static const nsInt64 gInterval((PRUint32)(400 * PR_USEC_PER_MSEC));
|
||||
|
||||
static nsIRDFResource* gNC_DownloadsRoot = nsnull;
|
||||
static nsIRDFResource* gNC_File = nsnull;
|
||||
@ -900,10 +902,11 @@ nsDownload::nsDownload(nsDownloadManager* aManager,
|
||||
mCancelable(aCancelable),
|
||||
mDownloadState(NOTSTARTED),
|
||||
mPercentComplete(0),
|
||||
mCurrBytes(0),
|
||||
mMaxBytes(0),
|
||||
mStartTime(0),
|
||||
mLastUpdate(-500)
|
||||
mCurrBytes(LL_ZERO),
|
||||
mMaxBytes(LL_ZERO),
|
||||
mStartTime(LL_ZERO),
|
||||
mSpeed(0),
|
||||
mLastUpdate(PR_Now() - (PRUint32)gInterval)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1027,10 +1030,9 @@ nsDownload::OnProgressChange64(nsIWebProgress *aWebProgress,
|
||||
mRequest = aRequest; // used for pause/resume
|
||||
|
||||
// filter notifications since they come in so frequently
|
||||
PRTime delta;
|
||||
PRTime now = PR_Now();
|
||||
LL_SUB(delta, now, mLastUpdate);
|
||||
if (LL_CMP(delta, <, INTERVAL) && aMaxTotalProgress != -1 && aCurTotalProgress < aMaxTotalProgress)
|
||||
nsInt64 delta = now - mLastUpdate;
|
||||
if (delta < gInterval)
|
||||
return NS_OK;
|
||||
|
||||
mLastUpdate = now;
|
||||
@ -1044,6 +1046,21 @@ nsDownload::OnProgressChange64(nsIWebProgress *aWebProgress,
|
||||
mDownloadManager->DownloadStarted(path);
|
||||
}
|
||||
|
||||
// Calculate the speed using the elapsed delta time and bytes downloaded
|
||||
// during that time for more accuracy.
|
||||
double elapsedSecs = double(delta) / PR_USEC_PER_SEC;
|
||||
if (elapsedSecs > 0) {
|
||||
nsUint64 curTotalProgress = (PRUint64)aCurTotalProgress;
|
||||
nsUint64 diffBytes = curTotalProgress - nsUint64(mCurrBytes);
|
||||
double speed = double(diffBytes) / elapsedSecs;
|
||||
if (LL_IS_ZERO(mCurrBytes))
|
||||
mSpeed = speed;
|
||||
else {
|
||||
// Calculate 'smoothed average' of 10 readings.
|
||||
mSpeed = mSpeed * 0.9 + speed * 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
if (aMaxTotalProgress > 0)
|
||||
mPercentComplete = aCurTotalProgress * 100 / aMaxTotalProgress;
|
||||
else
|
||||
@ -1196,8 +1213,9 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest, PRUint32 aStateFlags,
|
||||
nsresult aStatus)
|
||||
{
|
||||
if (aStateFlags & STATE_START)
|
||||
mStartTime = PR_Now();
|
||||
// Record the start time only if it hasn't been set.
|
||||
if (LL_IS_ZERO(mStartTime) && (aStateFlags & STATE_START))
|
||||
SetStartTime(PR_Now());
|
||||
|
||||
// When we break the ref cycle with mPersist, we don't want to lose
|
||||
// access to out member vars!
|
||||
@ -1210,7 +1228,7 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
|
||||
if (mDownloadState == DOWNLOADING || mDownloadState == NOTSTARTED) {
|
||||
mDownloadState = FINISHED;
|
||||
|
||||
// Set file size at the end of a tranfer (for unknown transfer amounts)
|
||||
// Set file size at the end of a tranfer (for unknown transfer amounts)
|
||||
if (mMaxBytes == -1)
|
||||
mMaxBytes = mCurrBytes;
|
||||
|
||||
@ -1409,3 +1427,10 @@ nsDownload::GetTargetFile(nsILocalFile** aTargetFile)
|
||||
rv = CallQueryInterface(file, aTargetFile);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownload::GetSpeed(double* aSpeed)
|
||||
{
|
||||
*aSpeed = mSpeed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -159,6 +159,7 @@ public:
|
||||
}
|
||||
void SetStartTime(PRInt64 aStartTime) {
|
||||
mStartTime = aStartTime;
|
||||
mLastUpdate = aStartTime;
|
||||
}
|
||||
private:
|
||||
nsDownloadManager* mDownloadManager;
|
||||
@ -179,6 +180,7 @@ private:
|
||||
PRUint64 mMaxBytes;
|
||||
PRTime mStartTime;
|
||||
PRTime mLastUpdate;
|
||||
double mSpeed;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -43,7 +43,6 @@ function nsDownloadProgressListener() {
|
||||
}
|
||||
|
||||
nsDownloadProgressListener.prototype = {
|
||||
elapsed: 0,
|
||||
rateChanges: 0,
|
||||
rateChangeLimit: 0,
|
||||
priorRate: "",
|
||||
@ -93,14 +92,6 @@ nsDownloadProgressListener.prototype = {
|
||||
// Update this time.
|
||||
this.lastUpdate = now;
|
||||
|
||||
// Update download rate.
|
||||
this.elapsed = now - (aDownload.startTime / 1000);
|
||||
var rate; // aCurTotalProgress/sec
|
||||
if ( this.elapsed )
|
||||
rate = ( aCurTotalProgress * 1000 ) / this.elapsed;
|
||||
else
|
||||
rate = 0;
|
||||
|
||||
var aDownloadID = aDownload.targetFile.path
|
||||
var elt = this.doc.getElementById(aDownloadID).firstChild.firstChild;
|
||||
if (this.doc.getElementById("TimeElapsed").getAttribute("hidden") != "true") {
|
||||
@ -144,6 +135,7 @@ nsDownloadProgressListener.prototype = {
|
||||
status = replaceInsert( status, 2, "??" );
|
||||
|
||||
var rateMsg = getString( "rateMsg", this.doc );
|
||||
var rate = aDownload.speed;
|
||||
if ( rate )
|
||||
{
|
||||
// rate is bytes/sec
|
||||
|
Loading…
Reference in New Issue
Block a user