зеркало из https://github.com/mozilla/pjs.git
Fixes for bugs 22296, 19019, et al; r=matt@netscape.com
This commit is contained in:
Родитель
782a39ee6a
Коммит
f9dafb59ba
|
@ -38,7 +38,11 @@ var observer = {
|
|||
onProgress( words[0], words[1] );
|
||||
break;
|
||||
case progId+";onStatus":
|
||||
onStatus( data );
|
||||
// Ignore useless "Transferring data..." messages
|
||||
// after download has started.
|
||||
if ( !started ) {
|
||||
onStatus( data );
|
||||
}
|
||||
break;
|
||||
case progId+";onCompletion":
|
||||
onCompletion( data );
|
||||
|
@ -54,6 +58,29 @@ var observer = {
|
|||
}
|
||||
}
|
||||
|
||||
function getString( stringId ) {
|
||||
// Check if we've fetched this string already.
|
||||
if ( !dialog.strings[ stringId ] ) {
|
||||
// Try to get it.
|
||||
var elem = document.getElementById( "dialog.strings."+stringId );
|
||||
if ( elem ) {
|
||||
dialog.strings[ stringId ] = elem.childNodes[0].nodeValue;
|
||||
}
|
||||
// If missing, use "?" instead.
|
||||
if ( !dialog.strings[ stringId ] ) {
|
||||
dialogs.strings[ stringId ] = "?";
|
||||
}
|
||||
}
|
||||
return dialog.strings[ stringId ];
|
||||
}
|
||||
|
||||
function replaceInsert( text, index, value ) {
|
||||
var result = text;
|
||||
var regExp = eval( "/#"+index+"/" );
|
||||
result = result.replace( regExp, value );
|
||||
return result;
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
// Set global variables.
|
||||
data = window.arguments[0];
|
||||
|
@ -64,6 +91,7 @@ function onLoad() {
|
|||
}
|
||||
|
||||
dialog = new Object;
|
||||
dialog.strings = new Array;
|
||||
dialog.location = document.getElementById("dialog.location");
|
||||
dialog.contentType = document.getElementById("dialog.contentType");
|
||||
dialog.fileName = document.getElementById("dialog.fileName");
|
||||
|
@ -71,6 +99,7 @@ function onLoad() {
|
|||
dialog.progress = document.getElementById("dialog.progress");
|
||||
dialog.progressPercent = document.getElementById("dialog.progressPercent");
|
||||
dialog.timeLeft = document.getElementById("dialog.timeLeft");
|
||||
dialog.timeElapsed = document.getElementById("dialog.timeElapsed");
|
||||
dialog.cancel = document.getElementById("dialog.cancel");
|
||||
|
||||
// Fill dialog.
|
||||
|
@ -99,12 +128,33 @@ var elapsed;
|
|||
var interval = 1000; // Update every 1000 milliseconds.
|
||||
var lastUpdate = -interval; // Update initially.
|
||||
|
||||
function stop() {
|
||||
// Stop the transfer.
|
||||
data.Stop();
|
||||
// These are to throttle down the updating of the download rate figure.
|
||||
var priorRate = 0;
|
||||
var rateChanges = 0;
|
||||
var rateChangeLimit = 2;
|
||||
|
||||
// Close the window.
|
||||
window.close();
|
||||
var warningLimit = 30000; // Warn on Cancel after 30 sec (30000 milleseconds).
|
||||
|
||||
function stop() {
|
||||
// If too much time has elapsed, make sure it's OK to quit.
|
||||
if ( started ) {
|
||||
// Get current time.
|
||||
var now = ( new Date() ).getTime();
|
||||
|
||||
// See if sufficient time has elapsed to warrant dialog.
|
||||
if ( now - startTime > warningLimit ) {
|
||||
// XXX - Disabled for now since confirm call doesn't work.
|
||||
if ( 0 && !window.confirm( getString( "confirmCancel" ) ) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the transfer.
|
||||
data.Stop();
|
||||
|
||||
// Close the window.
|
||||
window.close();
|
||||
}
|
||||
|
||||
function onProgress( bytes, max ) {
|
||||
|
@ -138,10 +188,16 @@ function onProgress( bytes, max ) {
|
|||
rate = 0;
|
||||
}
|
||||
|
||||
// Update elapsed time display.
|
||||
dialog.timeElapsed.childNodes[0].nodeValue = formatSeconds( elapsed / 1000 );
|
||||
|
||||
// Calculate percentage.
|
||||
var percent;
|
||||
if ( max != "-1" ) {
|
||||
percent = Math.round( (bytes*100)/max );
|
||||
percent = parseInt( (bytes*100)/max + .5 );
|
||||
if ( percent > 100 ) {
|
||||
percent = 100;
|
||||
}
|
||||
|
||||
// Advance progress meter.
|
||||
dialog.progress.setAttribute( "value", percent );
|
||||
|
@ -154,37 +210,61 @@ function onProgress( bytes, max ) {
|
|||
|
||||
// Check if download complete.
|
||||
if ( !completed ) {
|
||||
// Update status (nnn of mmm)
|
||||
var status = "( ";
|
||||
status += Math.round( bytes/1024 );
|
||||
status += "K of ";
|
||||
// Update status (nnK of mmK bytes at xx.xK bytes/sec)
|
||||
var status = getString( "progressMsg" );
|
||||
|
||||
// Insert 1 is the number of kilobytes downloaded so far.
|
||||
status = replaceInsert( status, 1, parseInt( bytes/1024 + .5 ) );
|
||||
|
||||
// Insert 2 is the total number of kilobytes to be downloaded (if known).
|
||||
if ( max != "-1" ) {
|
||||
status += Math.round( max/1024 );
|
||||
status += "K bytes ";
|
||||
status = replaceInsert( status, 2, parseInt( max/1024 + .5 ) );
|
||||
} else {
|
||||
status += "??.?K bytes ";
|
||||
status = replaceInsert( status, 2, "??" );
|
||||
}
|
||||
|
||||
if ( rate ) {
|
||||
status += "at ";
|
||||
status += Math.round( (rate*10)/1024 ) / 10;
|
||||
status += "K bytes/sec )";
|
||||
// rate is bytes/sec
|
||||
var kRate = rate / 1024; // K bytes/sec;
|
||||
kRate = parseInt( kRate * 10 + .5 ); // xxx (3 digits)
|
||||
// Don't update too often!
|
||||
if ( kRate != priorRate ) {
|
||||
if ( rateChanges++ == rateChangeLimit ) {
|
||||
// Time to update download rate.
|
||||
priorRate = kRate;
|
||||
rateChanges = 0;
|
||||
} else {
|
||||
// Stick with old rate for a bit longer.
|
||||
kRate = priorRate;
|
||||
}
|
||||
} else {
|
||||
rateChanges = 0;
|
||||
}
|
||||
var fraction = kRate % 10;
|
||||
kRate = parseInt( ( kRate - fraction ) / 10 );
|
||||
|
||||
// Insert 3 is the download rate (in kilobytes/sec).
|
||||
status = replaceInsert( status, 3, kRate + "." + fraction );
|
||||
} else {
|
||||
status += ")";
|
||||
status = replaceInsert( status, 3, "??.?" );
|
||||
}
|
||||
// Update status msg.
|
||||
onStatus( status );
|
||||
}
|
||||
|
||||
// Update percentage label on progress meter.
|
||||
dialog.progressPercent.childNodes[0].nodeValue = percent + "%";
|
||||
var percentMsg = getString( "percentMsg" );
|
||||
percentMsg = replaceInsert( percentMsg, 1, percent );
|
||||
dialog.progressPercent.childNodes[0].nodeValue = percentMsg;
|
||||
|
||||
if ( !completed ) {
|
||||
// Update time remaining.
|
||||
if ( rate && max != "-1" ) {
|
||||
var rem = Math.round( ( max - bytes ) / rate ); // In seconds.
|
||||
var rem = ( max - bytes ) / rate;
|
||||
rem = parseInt( rem + .5 );
|
||||
dialog.timeLeft.childNodes[0].nodeValue = formatSeconds( rem );
|
||||
} else {
|
||||
dialog.timeLeft.childNodes[0].nodeValue = "??:??:??";
|
||||
dialog.timeLeft.childNodes[0].nodeValue = getString( "unknownTime" );
|
||||
}
|
||||
} else {
|
||||
// Clear time remaining field.
|
||||
|
@ -192,43 +272,53 @@ function onProgress( bytes, max ) {
|
|||
}
|
||||
}
|
||||
|
||||
function formatSeconds( nSecs ) {
|
||||
status = "";
|
||||
if ( nSecs >= 3600 ) {
|
||||
status += Math.round( nSecs/3600 ) + ":";
|
||||
nSecs = nSecs % 3600;
|
||||
function formatSeconds( secs ) {
|
||||
// Round the number of seconds to remove fractions.
|
||||
secs = parseInt( secs + .5 );
|
||||
var hours = parseInt( secs/3600 );
|
||||
secs -= hours*3600;
|
||||
var mins = parseInt( secs/60 );
|
||||
secs -= mins*60;
|
||||
var result;
|
||||
if ( hours ) {
|
||||
result = getString( "longTimeFormat" );
|
||||
} else {
|
||||
result = getString( "shortTimeFormat" );
|
||||
}
|
||||
status += Math.round( nSecs/60 ) + ":";
|
||||
nSecs = nSecs % 60;
|
||||
status += nSecs;
|
||||
return status;
|
||||
if ( hours < 10 ) {
|
||||
hours = "0" + hours;
|
||||
}
|
||||
if ( mins < 10 ) {
|
||||
mins = "0" + mins;
|
||||
}
|
||||
if ( secs < 10 ) {
|
||||
secs = "0" + secs;
|
||||
}
|
||||
// Insert hours, minutes, and seconds into result string.
|
||||
result = replaceInsert( result, 1, hours );
|
||||
result = replaceInsert( result, 2, mins );
|
||||
result = replaceInsert( result, 3, secs );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function onCompletion( status ) {
|
||||
// Note that we're done (and can ignore subsequent progress notifications).
|
||||
completed = true;
|
||||
// Indicate completion in status area.
|
||||
onStatus( "Download completed in " + formatSeconds( elapsed/1000 ) );
|
||||
var msg = getString( "completeMsg" );
|
||||
msg = replaceInsert( msg, 1, formatSeconds( elapsed/1000 ) );
|
||||
onStatus( msg );
|
||||
|
||||
// Put progress meter at 100%.
|
||||
dialog.progress.setAttribute( "value", 100 );
|
||||
dialog.progress.setAttribute( "mode", "normal" );
|
||||
try {
|
||||
// Close the window in 2 seconds (to ensure user sees we're done).
|
||||
//window.setTimeout( "window.close();", 2000 );
|
||||
// The above line causes crash on Mac (see bugzilla bug #10613).
|
||||
// As a workaround, change button text to "Close" and try a
|
||||
// simple close(). Note that the "close()" is also failing (silently)
|
||||
// thus the need for the fail-safe mechanism (changing the button
|
||||
// text).
|
||||
dialog.cancel.childNodes[0].nodeValue = "Close";
|
||||
window.close();
|
||||
dump( "Close still not working right!\n" );
|
||||
window.setTimeout( "window.close();", 2000 );
|
||||
} catch ( exception ) {
|
||||
dump( "Error setting close timeout\n" );
|
||||
for ( prop in exception ) {
|
||||
dump( "exception." + prop + "=" + exception[ prop ] + "\n" );
|
||||
}
|
||||
// Bug prevents that from working, just close the window.
|
||||
// OK, try to just close the window immediately.
|
||||
window.close();
|
||||
// If that's not working either, change button text to give user a clue.
|
||||
dialog.cancel.childNodes[0].nodeValue = "Close";
|
||||
|
@ -236,8 +326,12 @@ function onCompletion( status ) {
|
|||
}
|
||||
|
||||
function onStatus( status ) {
|
||||
// Update status text in dialog.
|
||||
dialog.status.childNodes[0].nodeValue = status;
|
||||
// Update status text in dialog.
|
||||
// Ignore if status text is less than 10 characters (we're getting some
|
||||
// bogus onStatus notifications.
|
||||
if ( status.length > 9 ) {
|
||||
dialog.status.childNodes[0].nodeValue = status;
|
||||
}
|
||||
}
|
||||
|
||||
function onError( errorCode ) {
|
||||
|
|
|
@ -1,15 +1,31 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://navigator/skin/" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://global/locale/downloadProgress.dtd">
|
||||
|
||||
<window xmlns:html="http://www.w3.org/TR/REC-html40"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
class="dialog"
|
||||
title="Saving file"
|
||||
onload="onLoad()"
|
||||
onunload="onUnload()">
|
||||
|
||||
<html:script src="chrome://global/content/downloadProgress.js"/>
|
||||
|
||||
<!-- This is non-visible content that simply adds translatable string
|
||||
into the document so that it is accessible to JS code.
|
||||
-->
|
||||
<html:div style="display:none">
|
||||
<html:div id="dialog.strings.confirmCancel">&confirmCancel;</html:div>
|
||||
<html:div id="dialog.strings.progressMsg">&progressMsg;</html:div>
|
||||
<html:div id="dialog.strings.completeMsg">&completeMsg;</html:div>
|
||||
<html:div id="dialog.strings.percentMsg">&percentMsg;</html:div>
|
||||
<html:div id="dialog.strings.shortTimeFormat">&shortTimeFormat;</html:div>
|
||||
<html:div id="dialog.strings.longTimeFormat">&longTimeFormat;</html:div>
|
||||
<html:div id="dialog.strings.unknownTime">&unknownTime;</html:div>
|
||||
</html:div>
|
||||
|
||||
<html:table style="width:100%;">
|
||||
|
||||
<html:tr>
|
||||
|
@ -36,7 +52,18 @@
|
|||
</html:td>
|
||||
<html:td align="left">
|
||||
<html:span id="dialog.status">
|
||||
&dialogStatus.label;
|
||||
&progressMsg;
|
||||
</html:span>
|
||||
</html:td>
|
||||
</html:tr>
|
||||
|
||||
<html:tr>
|
||||
<html:td align="right">
|
||||
&timeElapsed;
|
||||
</html:td>
|
||||
<html:td align="left">
|
||||
<html:span id="dialog.timeElapsed">
|
||||
00:00:00
|
||||
</html:span>
|
||||
</html:td>
|
||||
</html:tr>
|
||||
|
@ -47,7 +74,7 @@
|
|||
</html:td>
|
||||
<html:td align="left">
|
||||
<html:span id="dialog.timeLeft">
|
||||
&dialogTimeLeft.label;
|
||||
00:00:00
|
||||
</html:span>
|
||||
</html:td>
|
||||
</html:tr>
|
||||
|
@ -57,7 +84,7 @@
|
|||
<progressmeter id="dialog.progress" mode="normal" value="0"
|
||||
style="width:300px;height:16px;"/>
|
||||
<html:span id="dialog.progressPercent" style="border-left:5px solid lightgray;">
|
||||
0%
|
||||
&percentMsg;
|
||||
</html:span>
|
||||
</html:td>
|
||||
</html:tr>
|
||||
|
|
|
@ -1,12 +1,67 @@
|
|||
<!-- extracted from downloadProgress.xul -->
|
||||
|
||||
<!ENTITY downloadWindow.title "Saving file">
|
||||
<!ENTITY location "Location">
|
||||
<!ENTITY saving "Saving">
|
||||
<!ENTITY status "Status:">
|
||||
<!-- LOCALIZATION NOTE (dialogStatus.label): Do NOT translate "nn.n" and "mm.m" -->
|
||||
<!ENTITY dialogStatus.label "( nn.nK of mm.mK bytes )">
|
||||
<!ENTITY timeLeft "Time Left:">
|
||||
<!ENTITY dialogTimeLeft.label "?">
|
||||
<!ENTITY location "Location">
|
||||
<!ENTITY saving "Saving">
|
||||
<!ENTITY status "Status:">
|
||||
|
||||
<!ENTITY timeElapsed "Elapsed Time:">
|
||||
<!ENTITY timeLeft "Time Left:">
|
||||
|
||||
<!ENTITY dialogCancel.label "Cancel">
|
||||
|
||||
<!ENTITY confirmCancel "Are you sure you want to cancel the saving of this file?">
|
||||
|
||||
<!-- LOCALIZATION NOTE
|
||||
|
||||
This string is used to generate the status message used during
|
||||
file download.
|
||||
|
||||
#1 will be replaced by the number of bytes downloaded thus far
|
||||
#2 will be replaced by the total number of bytes to be downloaded
|
||||
#3 will be replaced by the download rate (in Kbytes per second) -->
|
||||
<!ENTITY progressMsg "#1K of #2K bytes (at #3K bytes/sec)">
|
||||
|
||||
<!-- LOCALIZATION NOTE
|
||||
|
||||
This string is used when the time remaining is unknown. -->
|
||||
<!ENTITY unknownTime "">
|
||||
|
||||
<!-- LOCALIZATION NOTE
|
||||
|
||||
This string is used to format elapsed/remaining times when the
|
||||
time exceeds 1 hour in length.
|
||||
|
||||
#1 will be replaced by the number of hours
|
||||
#2 will be replaced by the number of minutes
|
||||
#3 will be replaced by the number of seconds -->
|
||||
<!ENTITY longTimeFormat "#1:#2:#3">
|
||||
|
||||
<!-- LOCALIZATION NOTE
|
||||
|
||||
This string is used to format elapsed/remaining times when the
|
||||
time is less than 1 hour in length. Note that you can leave
|
||||
"#1" out of this string to omit the leading "00:" if you so choose.
|
||||
|
||||
#1 will be replaced by the number of hours
|
||||
#2 will be replaced by the number of minutes
|
||||
#3 will be replaced by the number of seconds -->
|
||||
<!ENTITY shortTimeFormat "#2:#3">
|
||||
|
||||
<!-- LOCALIZATION NOTE
|
||||
|
||||
This string is displayed when the download is complete. The insert
|
||||
"#1" is replaced by the elapsed time, formatted according to the
|
||||
xxxTimeFormat strings defined above). You can omit "#1" if you don't
|
||||
want the elapsed time in the message.
|
||||
|
||||
#1 will be replaced by the elapsed time -->
|
||||
<!ENTITY completeMsg "Download complete (elapsed time was #1)">
|
||||
|
||||
<!-- LOCALIZATION NOTE
|
||||
|
||||
This string is used to format the text to the right of the progress
|
||||
meter.
|
||||
|
||||
#1 will be replaced by the percentage of the file that has been saved -->
|
||||
<!ENTITY percentMsg "#1%">
|
||||
|
|
|
@ -332,11 +332,6 @@ nsStreamXferOp::OnStopRequest( nsIChannel *channel,
|
|||
const PRUnichar *aMsg ) {
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
#ifdef DEBUG_law
|
||||
DEBUG_PRINTF( PR_STDOUT, "nsStreamXferOp::OnStopRequest notified of input completion, status=0x%08X\n",
|
||||
(int)aStatus );
|
||||
#endif
|
||||
|
||||
// Close the output stream.
|
||||
if ( mOutputStream ) {
|
||||
rv = mOutputStream->Close();
|
||||
|
|
Загрузка…
Ссылка в новой задаче