📄 nsprogressdialog.js
字号:
/* vim:set ts=4 sts=4 sw=4 et cin: *//* ***** 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 Progress Dialog. * * The Initial Developer of the Original Code is * Netscape Communications Corp. * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Bill Law <law@netscape.com> * Aaron Kaluszka <ask@swva.net> * * 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 ***** *//* This file implements the nsIProgressDialog interface. See nsIProgressDialog.idl * * The implementation consists of a JavaScript "class" named nsProgressDialog, * comprised of: * - a JS constructor function * - a prototype providing all the interface methods and implementation stuff * * In addition, this file implements an nsIModule object that registers the * nsProgressDialog component. *//* ctor */function nsProgressDialog() { // Initialize data properties. this.mParent = null; this.mOperation = null; this.mStartTime = ( new Date() ).getTime(); this.observer = null; this.mLastUpdate = Number.MIN_VALUE; // To ensure first onProgress causes update. this.mInterval = 750; // Default to .75 seconds. this.mElapsed = 0; this.mLoaded = false; this.fields = new Array; this.strings = new Array; this.mSource = null; this.mTarget = null; this.mTargetFile = null; this.mMIMEInfo = null; this.mDialog = null; this.mDisplayName = null; this.mPaused = false; this.mRequest = null; this.mCompleted = false; this.mMode = "normal"; this.mPercent = -1; this.mRate = 0; this.mBundle = null; this.mCancelDownloadOnClose = true;}const nsIProgressDialog = Components.interfaces.nsIProgressDialog;const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;const nsITextToSubURI = Components.interfaces.nsITextToSubURI;const nsIChannel = Components.interfaces.nsIChannel;const nsIFileURL = Components.interfaces.nsIFileURL;const nsIURL = Components.interfaces.nsIURL;const nsILocalFile = Components.interfaces.nsILocalFile;nsProgressDialog.prototype = { // Turn this on to get debugging messages. debug: false, // Chrome-related constants. dialogChrome: "chrome://global/content/nsProgressDialog.xul", dialogFeatures: "chrome,titlebar,minimizable=yes,dialog=no", // getters/setters get saving() { return this.MIMEInfo == null || this.MIMEInfo.preferredAction == Components.interfaces.nsIMIMEInfo.saveToDisk; }, get parent() { return this.mParent; }, set parent(newval) { return this.mParent = newval; }, get operation() { return this.mOperation; }, set operation(newval) { return this.mOperation = newval; }, get observer() { return this.mObserver; }, set observer(newval) { return this.mObserver = newval; }, get startTime() { return this.mStartTime; }, set startTime(newval) { return this.mStartTime = newval/1000; }, // PR_Now() is in microseconds, so we convert. get lastUpdate() { return this.mLastUpdate; }, set lastUpdate(newval) { return this.mLastUpdate = newval; }, get interval() { return this.mInterval; }, set interval(newval) { return this.mInterval = newval; }, get elapsed() { return this.mElapsed; }, set elapsed(newval) { return this.mElapsed = newval; }, get loaded() { return this.mLoaded; }, set loaded(newval) { return this.mLoaded = newval; }, get source() { return this.mSource; }, set source(newval) { return this.mSource = newval; }, get target() { return this.mTarget; }, get targetFile() { return this.mTargetFile; }, get MIMEInfo() { return this.mMIMEInfo; }, set MIMEInfo(newval) { return this.mMIMEInfo = newval; }, get dialog() { return this.mDialog; }, set dialog(newval) { return this.mDialog = newval; }, get displayName() { return this.mDisplayName; }, set displayName(newval) { return this.mDisplayName = newval; }, get paused() { return this.mPaused; }, get completed() { return this.mCompleted; }, get mode() { return this.mMode; }, get percent() { return this.mPercent; }, get rate() { return this.mRate; }, get kRate() { return this.mRate / 1024; }, get cancelDownloadOnClose() { return this.mCancelDownloadOnClose; }, set cancelDownloadOnClose(newval) { return this.mCancelDownloadOnClose = newval; }, set target(newval) { // If newval references a file on the local filesystem, then grab a // reference to its corresponding nsIFile. if (newval instanceof nsIFileURL && newval.file instanceof nsILocalFile) { this.mTargetFile = newval.file.QueryInterface(nsILocalFile); } else { this.mTargetFile = null; } return this.mTarget = newval; }, // These setters use functions that update the dialog. set paused(newval) { return this.setPaused(newval); }, set completed(newval) { return this.setCompleted(newval); }, set mode(newval) { return this.setMode(newval); }, set percent(newval) { return this.setPercent(newval); }, set rate(newval) { return this.setRate(newval); }, // ---------- nsIProgressDialog methods ---------- // open: Store aParentWindow and open the dialog. open: function( aParentWindow ) { // Save parent and "persist" operation. this.parent = aParentWindow; // Open dialog using the WindowWatcher service. var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] .getService( nsIWindowWatcher ); this.dialog = ww.openWindow( this.parent, this.dialogChrome, null, this.dialogFeatures, this ); }, init: function( aSource, aTarget, aDisplayName, aMIMEInfo, aStartTime, aTempFile, aOperation ) { this.source = aSource; this.target = aTarget; this.displayName = aDisplayName; this.MIMEInfo = aMIMEInfo; if ( aStartTime ) { this.startTime = aStartTime; } this.operation = aOperation; }, // ---------- nsIWebProgressListener methods ---------- // Look for STATE_STOP and update dialog to indicate completion when it happens. onStateChange: function( aWebProgress, aRequest, aStateFlags, aStatus ) { if ( aStateFlags & nsIWebProgressListener.STATE_STOP ) { // if we are downloading, then just wait for the first STATE_STOP if ( this.targetFile != null ) { // we are done transferring... this.completed = true; return; } // otherwise, wait for STATE_STOP with aRequest corresponding to // our target. XXX redirects might screw up this logic. try { var chan = aRequest.QueryInterface(nsIChannel); if (chan.URI.equals(this.target)) { // we are done transferring... this.completed = true; } } catch (e) { } } }, // Handle progress notifications. onProgressChange: function( aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress ) { return onProgressChange64(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress); }, onProgressChange64: function( aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress ) { var overallProgress = aCurTotalProgress; // Get current time. var now = ( new Date() ).getTime(); // If interval hasn't elapsed, ignore it. if ( now - this.lastUpdate < this.interval && aMaxTotalProgress != "-1" && parseInt( aCurTotalProgress ) < parseInt( aMaxTotalProgress ) ) { return; } // Update this time. this.lastUpdate = now; // Update elapsed time. this.elapsed = now - this.startTime; // Calculate percentage. if ( aMaxTotalProgress > 0) { this.percent = Math.floor( ( overallProgress * 100.0 ) / aMaxTotalProgress ); } else { this.percent = -1; } // If dialog not loaded, then don't bother trying to update display. if ( !this.loaded ) { return; } // Update dialog's display of elapsed time. this.setValue( "timeElapsed", this.formatSeconds( this.elapsed / 1000 ) ); // Now that we've set the progress and the time, update # bytes downloaded... // Update status (nnK of mmK bytes at xx.xK aCurTotalProgress/sec) var status = this.getString( "progressMsg" ); // Insert 1 is the number of kilobytes downloaded so far. status = this.replaceInsert( status, 1, parseInt( overallProgress/1024 + .5 ) ); // Insert 2 is the total number of kilobytes to be downloaded (if known). if ( aMaxTotalProgress != "-1" ) { status = this.replaceInsert( status, 2, parseInt( aMaxTotalProgress/1024 + .5 ) ); } else { status = this.replaceInsert( status, 2, "??" ); } // Insert 3 is the download rate. if ( this.elapsed ) { this.rate = ( aCurTotalProgress * 1000 ) / this.elapsed; status = this.replaceInsert( status, 3, this.rateToKRate( this.rate ) ); } else { // Rate not established, yet. status = this.replaceInsert( status, 3, "??.?" ); } // All 3 inserts are taken care of, now update status msg. this.setValue( "status", status ); // Update time remaining. if ( this.rate && ( aMaxTotalProgress > 0 ) ) { // Calculate how much time to download remaining at this rate. var rem = Math.round( ( aMaxTotalProgress - aCurTotalProgress ) / this.rate ); this.setValue( "timeLeft", this.formatSeconds( rem ) ); } else { // We don't know how much time remains. this.setValue( "timeLeft", this.getString( "unknownTime" ) ); } }, // Look for error notifications and display alert to user. onStatusChange: function( aWebProgress, aRequest, aStatus, aMessage ) { // Check for error condition (only if dialog is still open). if ( aStatus != Components.results.NS_OK ) { if ( this.loaded ) { // Get prompt service. var prompter = Components.classes[ "@mozilla.org/embedcomp/prompt-service;1" ] .getService( Components.interfaces.nsIPromptService ); // Display error alert (using text supplied by back-end). var title = this.getProperty( this.saving ? "savingAlertTitle" : "openingAlertTitle", [ this.fileName() ], 1 ); prompter.alert( this.dialog, title, aMessage ); // Close the dialog. if ( !this.completed ) { this.onCancel(); } } else { // Error occurred prior to onload even firing. // We can't handle this error until we're done loading, so
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -