!import
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Blake Ross <blaker@netscape.com> (Original Author)
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39 var gStrings = new Array;
40 const interval = 500; // Update every 500 milliseconds.
41
nsDownloadProgressListener
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
42 function nsDownloadProgressListener() {
43 }
44
45 nsDownloadProgressListener.prototype = {
46 rateChanges: 0,
47 rateChangeLimit: 0,
48 priorRate: "",
49 lastUpdate: -500,
50 doc: null,
get_document
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
51 get document() {
52 return this.doc;
53 },
set_document
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
54 set document(newval) {
55 return this.doc = newval;
56 },
onStateChange
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
57 onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus, aDownload)
58 {
59 if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
60 {
61 var aDownloadID = aDownload.targetFile.path;
62 var elt = this.doc.getElementById(aDownloadID).firstChild.firstChild;
63
64 var timeRemainingCol = elt.nextSibling.nextSibling.nextSibling;
65 timeRemainingCol.setAttribute("label", "");
66
67 var speedCol = timeRemainingCol.nextSibling.nextSibling;
68 speedCol.setAttribute("label", "");
69
70 var elapsedCol = speedCol.nextSibling;
71 elapsedCol.setAttribute("label", "");
72
73 // Fire an onselect event for the downloadView element
74 // to update menu status
75 var event = this.doc.createEvent('Events');
76 event.initEvent('select', false, true);
77 this.doc.getElementById("downloadView").dispatchEvent(event);
78 }
79 },
80
onProgressChange
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
81 onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
82 aCurTotalProgress, aMaxTotalProgress, aDownload)
83 {
84 var overallProgress = aCurTotalProgress;
85 // Get current time.
86 var now = ( new Date() ).getTime();
87 // If interval hasn't elapsed, ignore it.
88 if ( now - this.lastUpdate < interval && aMaxTotalProgress != "-1" && parseInt(aCurTotalProgress) < parseInt(aMaxTotalProgress) ) {
89 return;
90 }
91
92 // Update this time.
93 this.lastUpdate = now;
94
95 var aDownloadID = aDownload.targetFile.path
96 var elt = this.doc.getElementById(aDownloadID).firstChild.firstChild;
97 if (this.doc.getElementById("TimeElapsed").getAttribute("hidden") != "true") {
98 elapsedCol = elt.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling;
99 // Update elapsed time display.
100 elapsedCol.setAttribute("label", formatSeconds( now / 1000 - aDownload.startTime / 1000000, this.doc ));
101 }
102 // Calculate percentage.
103 var percent;
104 var progressCol = elt.nextSibling;
105 if ( aMaxTotalProgress > 0)
106 {
107 percent = Math.floor((overallProgress*100.0)/aMaxTotalProgress);
108 if ( percent > 100 )
109 percent = 100;
110
111 // Advance progress meter.
112 progressCol.setAttribute( "value", percent );
113
114 progressCol.setAttribute("mode", "normal");
115 }
116 else
117 {
118 percent = -1;
119
120 // Progress meter should be barber-pole in this case.
121 progressCol.setAttribute( "mode", "undetermined" );
122 }
123
124 // now that we've set the progress and the time, update # bytes downloaded...
125 // Update status (nnK of mmK bytes at xx.xK aCurTotalProgress/sec)
126 var status = getString( "progressMsgNoRate", this.doc );
127
128 // Insert 1 is the number of kilobytes downloaded so far.
129 status = replaceInsert( status, 1, parseInt( overallProgress/1024 + .5 ) );
130
131 // Insert 2 is the total number of kilobytes to be downloaded (if known).
132 if ( aMaxTotalProgress != "-1" )
133 status = replaceInsert( status, 2, parseInt( aMaxTotalProgress/1024 + .5 ) );
134 else
135 status = replaceInsert( status, 2, "??" );
136
137 var rateMsg = getString( "rateMsg", this.doc );
138 var rate = aDownload.speed;
139 if ( rate )
140 {
141 // rate is bytes/sec
142 var kRate = (rate / 1024).toFixed(1); // kilobytes/sec
143
144 // Don't update too often!
145 if ( kRate != this.priorRate )
146 {
147 if ( this.rateChanges++ == this.rateChangeLimit )
148 {
149 // Time to update download rate.
150 this.priorRate = kRate;
151 this.rateChanges = 0;
152 }
153 else
154 {
155 // Stick with old rate for a bit longer.
156 kRate = this.priorRate;
157 }
158 }
159 else
160 this.rateChanges = 0;
161
162 // Insert 3 is the download rate (in kilobytes/sec).
163 rateMsg = replaceInsert( rateMsg, 1, kRate );
164 }
165 else
166 rateMsg = replaceInsert( rateMsg, 1, "??.?" );
167
168 var timeRemainingCol = elt.nextSibling.nextSibling.nextSibling;
169
170 // Update status msg.
171 var statusCol = timeRemainingCol.nextSibling;
172 statusCol.setAttribute("label", status);
173
174 var speedCol = statusCol.nextSibling;
175 speedCol.setAttribute("label", rateMsg);
176 // Update percentage label on progress meter.
177 if (this.doc.getElementById("ProgressPercent").getAttribute("hidden") != "true") {
178 var progressText = elt.nextSibling.nextSibling;
179 if (percent < 0)
180 progressText.setAttribute("label", "");
181 else {
182 var percentMsg = getString( "percentMsg", this.doc );
183 percentMsg = replaceInsert( percentMsg, 1, percent );
184 progressText.setAttribute("label", percentMsg);
185 }
186 }
187 // Update time remaining.
188 if ( rate && (aMaxTotalProgress > 0) )
189 {
190 var rem = ( aMaxTotalProgress - aCurTotalProgress ) / rate;
191 rem = parseInt( rem + .5 );
192 timeRemainingCol.setAttribute("label", formatSeconds( rem, this.doc ));
193 }
194 else
195 timeRemainingCol.setAttribute("label", getString( "unknownTime", this.doc ));
196 },
onLocationChange
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
197 onLocationChange: function(aWebProgress, aRequest, aLocation, aDownload)
198 {
199 },
onStatusChange
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
200 onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage, aDownload)
201 {
202 },
onSecurityChange
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
203 onSecurityChange: function(aWebProgress, aRequest, state, aDownload)
204 {
205 },
QueryInterface
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
206 QueryInterface : function(iid)
207 {
208 if (iid.equals(Components.interfaces.nsIDownloadProgressListener) ||
209 iid.equals(Components.interfaces.nsISupports))
210 return this;
211
212 throw Components.results.NS_NOINTERFACE;
213 }
214 };
215
216 var nsDownloadProgressListenerFactory = {
createInstance
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
217 createInstance: function (outer, iid) {
218 if (outer != null)
219 throw Components.results.NS_ERROR_NO_AGGREGATION;
220
221 return (new nsDownloadProgressListener()).QueryInterface(iid);
222 }
223 };
224
225 var nsDownloadProgressListenerModule = {
226
registerSelf
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
227 registerSelf: function (compMgr, fileSpec, location, type)
228 {
229 var compReg = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
230 compReg.registerFactoryLocation(Components.ID("{09cddbea-1dd2-11b2-aa15-c41ffea19d79}"),
231 "Download Progress Listener",
232 "@mozilla.org/download-manager/listener;1",
233 fileSpec, location, type);
234 },
canUnload
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
235 canUnload: function(compMgr)
236 {
237 return true;
238 },
239
getClassObject
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
240 getClassObject: function (compMgr, cid, iid) {
241 if (!cid.equals(Components.ID("{09cddbea-1dd2-11b2-aa15-c41ffea19d79}")))
242 throw Components.results.NS_ERROR_NO_INTERFACE;
243
244 if (!iid.equals(Components.interfaces.nsIFactory))
245 throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
246
247 return nsDownloadProgressListenerFactory;
248 }
249 };
250
NSGetModule
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
251 function NSGetModule(compMgr, fileSpec) {
252 return nsDownloadProgressListenerModule;
253 }
254
replaceInsert
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
255 function replaceInsert( text, index, value ) {
256 var result = text;
257 var regExp = new RegExp( "#"+index );
258 result = result.replace( regExp, value );
259 return result;
260 }
261
getString
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
262 function getString( stringId, doc ) {
263 // Check if we've fetched this string already.
264 if ( !gStrings[ stringId ] ) {
265 // Try to get it.
266 var elem = doc.getElementById( "strings."+stringId );
267 try {
268 if ( elem
269 &&
270 elem.childNodes
271 &&
272 elem.childNodes[0]
273 &&
274 elem.childNodes[0].nodeValue ) {
275 gStrings[ stringId ] = elem.childNodes[0].nodeValue;
276 } else {
277 // If unable to fetch string, use an empty string.
278 gStrings[ stringId ] = "";
279 }
280 } catch (e) { gStrings[ stringId ] = ""; }
281 }
282 return gStrings[ stringId ];
283 }
284
formatSeconds
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
285 function formatSeconds( secs, doc )
286 {
287 // Round the number of seconds to remove fractions.
288 secs = parseInt( secs + .5 );
289 var hours = parseInt( secs/3600 );
290 secs -= hours*3600;
291 var mins = parseInt( secs/60 );
292 secs -= mins*60;
293 var result;
294 if ( hours )
295 result = getString( "longTimeFormat", doc );
296 else
297 result = getString( "shortTimeFormat", doc );
298
299 if ( hours < 10 )
300 hours = "0" + hours;
301 if ( mins < 10 )
302 mins = "0" + mins;
303 if ( secs < 10 )
304 secs = "0" + secs;
305
306 // Insert hours, minutes, and seconds into result string.
307 result = replaceInsert( result, 1, hours );
308 result = replaceInsert( result, 2, mins );
309 result = replaceInsert( result, 3, secs );
310
311 return result;
312 }