home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 January / 01_02.iso / software / netscape62win / browser.xpi / bin / chrome / toolkit.jar / content / global / helperAppDldProgress.js < prev    next >
Encoding:
JavaScript  |  2001-10-16  |  15.1 KB  |  483 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "License"); you may not use this file except in
  5.  * compliance with the License.  You may obtain a copy of the License at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  10.  * for the specific language governing rights and limitations under the
  11.  * License.
  12.  *
  13.  * The Original Code is Mozilla Communicator client code,
  14.  * released March 31, 1998.
  15.  *
  16.  * The Initial Developer of the Original Code is Netscape Communications
  17.  * Corporation.  Portions created by Netscape are
  18.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  19.  * Reserved.
  20.  *
  21.  * Contributors:
  22.  *     William A. ("PowerGUI") Law <law@netscape.com>
  23.  *     Scott MacGregor <mscott@netscape.com>
  24.  */
  25.  
  26. var prefContractID             = "@mozilla.org/preferences;1";
  27. var externalProtocolServiceID = "@mozilla.org/uriloader/external-protocol-service;1";
  28.  
  29. // dialog is just an array we'll use to store various properties from the dialog document...
  30. var dialog;
  31.  
  32. // the helperAppLoader is a nsIHelperAppLauncher object
  33. var helperAppLoader;
  34.  
  35. // random global variables...
  36. var completed = false;
  37. var startTime = 0;
  38. var elapsed = 0;
  39. var interval = 500; // Update every 500 milliseconds.
  40. var lastUpdate = -interval; // Update initially.
  41. var keepProgressWindowUpBox;
  42. var targetFile;
  43. var gRestartChecked = false;
  44.  
  45. // These are to throttle down the updating of the download rate figure.
  46. var priorRate = 0;
  47. var rateChanges = 0;
  48. var rateChangeLimit = 2;
  49.  
  50. // all progress notifications are done through our nsIWebProgressListener implementation...
  51. var progressListener = {
  52.     onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus)
  53.     {
  54.       if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
  55.       {
  56.         // we are done downloading...
  57.         completed = true;
  58.         // Indicate completion in status area.
  59.         var msg = getString( "completeMsg" );
  60.         msg = replaceInsert( msg, 1, formatSeconds( elapsed/1000 ) );
  61.         dialog.status.setAttribute("value", msg);
  62.  
  63.         // Put progress meter at 100%.
  64.         dialog.progress.setAttribute( "value", 100 );
  65.         dialog.progress.setAttribute( "mode", "normal" );
  66.         var percentMsg = getString( "percentMsg" );
  67.         percentMsg = replaceInsert( percentMsg, 1, 100 );
  68.         dialog.progressText.setAttribute("label", percentMsg);
  69.  
  70.         processEndOfDownload();
  71.       }
  72.     },
  73.  
  74.     onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
  75.     {
  76.  
  77.       if (!gRestartChecked) 
  78.       {
  79.         gRestartChecked = true;
  80.         try 
  81.         {
  82.           // right now, all that supports restarting downloads is ftp (rfc959)    
  83.           ftpChannel = aRequest.QueryInterface(Components.interfaces.nsIFTPChannel);
  84.           if (ftpChannel) {
  85.             dialog.pauseResumeDeck.setAttribute("index", "1");
  86.           }
  87.         }
  88.         catch (ex) {}
  89.       }
  90.  
  91.       // this is so that we don't clobber the status text if 
  92.       // a onProgressChange event happens after we press the pause btn.
  93.       if (dialog.downloadPaused) 
  94.       {
  95.         dialog.status.setAttribute("value", getString("pausedMsg"));
  96.       }
  97.  
  98.       dialog.request = aRequest;  
  99.  
  100.       var overallProgress = aCurTotalProgress;
  101.  
  102.       // Get current time.
  103.       var now = ( new Date() ).getTime();
  104.       // If interval hasn't elapsed, ignore it.
  105.       if ( now - lastUpdate < interval && aMaxTotalProgress != "-1" &&  parseInt(aCurTotalProgress) < parseInt(aMaxTotalProgress) )
  106.         return;
  107.  
  108.       // Update this time.
  109.       lastUpdate = now;
  110.  
  111.       // Update download rate.
  112.       elapsed = now - startTime;
  113.       var rate; // aCurTotalProgress/sec
  114.       if ( elapsed )
  115.         rate = ( aCurTotalProgress * 1000 ) / elapsed;
  116.       else
  117.         rate = 0;
  118.  
  119.       // Update elapsed time display.
  120.       dialog.timeElapsed.setAttribute("value", formatSeconds( elapsed / 1000 ));
  121.  
  122.       // Calculate percentage.
  123.       var percent;
  124.       if ( aMaxTotalProgress > 0)
  125.       {
  126.         percent = parseInt( (overallProgress*100)/aMaxTotalProgress + .5 );
  127.         if ( percent > 100 )
  128.           percent = 100;
  129.  
  130.         // Advance progress meter.
  131.         dialog.progress.setAttribute( "value", percent );
  132.       }
  133.       else
  134.       {
  135.         percent = -1;
  136.  
  137.         // Progress meter should be barber-pole in this case.
  138.         dialog.progress.setAttribute( "mode", "undetermined" );
  139.       }
  140.  
  141.       // now that we've set the progress and the time, update # bytes downloaded...
  142.       // Update status (nnK of mmK bytes at xx.xK aCurTotalProgress/sec)
  143.       var status = getString( "progressMsg" );
  144.  
  145.       // Insert 1 is the number of kilobytes downloaded so far.
  146.       status = replaceInsert( status, 1, parseInt( overallProgress/1024 + .5 ) );
  147.  
  148.       // Insert 2 is the total number of kilobytes to be downloaded (if known).
  149.       if ( aMaxTotalProgress != "-1" )
  150.          status = replaceInsert( status, 2, parseInt( aMaxTotalProgress/1024 + .5 ) );
  151.       else
  152.          status = replaceInsert( status, 2, "??" );
  153.  
  154.       if ( rate )
  155.       {
  156.         // rate is bytes/sec
  157.         var kRate = rate / 1024; // K bytes/sec;
  158.         kRate = parseInt( kRate * 10 + .5 ); // xxx (3 digits)
  159.         // Don't update too often!
  160.         if ( kRate != priorRate )
  161.         {
  162.           if ( rateChanges++ == rateChangeLimit )
  163.           {
  164.              // Time to update download rate.
  165.              priorRate = kRate;
  166.              rateChanges = 0;
  167.           }
  168.           else
  169.           {
  170.             // Stick with old rate for a bit longer.
  171.             kRate = priorRate;
  172.           }
  173.         }
  174.         else
  175.           rateChanges = 0;
  176.  
  177.          var fraction = kRate % 10;
  178.          kRate = parseInt( ( kRate - fraction ) / 10 );
  179.  
  180.          // Insert 3 is the download rate (in kilobytes/sec).
  181.          status = replaceInsert( status, 3, kRate + "." + fraction );
  182.       }
  183.       else
  184.        status = replaceInsert( status, 3, "??.?" );
  185.  
  186.       // Update status msg.
  187.       dialog.status.setAttribute("value", status);
  188.  
  189.       // Update percentage label on progress meter.      
  190.       if (percent < 0)
  191.         dialog.progressText.setAttribute("value", "");
  192.       else
  193.       {
  194.         var percentMsg = getString( "percentMsg" );      
  195.         percentMsg = replaceInsert( percentMsg, 1, percent );
  196.         dialog.progressText.setAttribute("value", percentMsg);
  197.       }
  198.  
  199.       // Update time remaining.
  200.       if ( rate && (aMaxTotalProgress > 0) )
  201.       {
  202.         var rem = ( aMaxTotalProgress - aCurTotalProgress ) / rate;
  203.         rem = parseInt( rem + .5 );
  204.         dialog.timeLeft.setAttribute("value", formatSeconds( rem ));
  205.       }
  206.       else
  207.         dialog.timeLeft.setAttribute("value", getString( "unknownTime" ));
  208.     },
  209.     onLocationChange: function(aWebProgress, aRequest, aLocation)
  210.     {
  211.       // we can ignore this notification
  212.     },
  213.     onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage)
  214.     {
  215.     },
  216.     onSecurityChange: function(aWebProgress, aRequest, state)
  217.     {
  218.     },
  219.     QueryInterface : function(iid)
  220.     {
  221.      if (iid.equals(Components.interfaces.nsIWebProgressListener) || iid.equals(Components.interfaces.nsISupportsWeakReference))
  222.       return this;
  223.  
  224.      throw Components.results.NS_NOINTERFACE;
  225.     }
  226. };
  227.  
  228. function getString( stringId ) {
  229.    // Check if we've fetched this string already.
  230.    if ( !dialog.strings[ stringId ] ) {
  231.       // Try to get it.
  232.       var elem = document.getElementById( "dialog.strings."+stringId );
  233.       try {
  234.         if ( elem
  235.            &&
  236.            elem.childNodes
  237.            &&
  238.            elem.childNodes[0]
  239.            &&
  240.            elem.childNodes[0].nodeValue ) {
  241.          dialog.strings[ stringId ] = elem.childNodes[0].nodeValue;
  242.         } else {
  243.           // If unable to fetch string, use an empty string.
  244.           dialog.strings[ stringId ] = "";
  245.         }
  246.       } catch (e) { dialog.strings[ stringId ] = ""; }
  247.    }
  248.    return dialog.strings[ stringId ];
  249. }
  250.  
  251. function formatSeconds( secs )
  252. {
  253.   // Round the number of seconds to remove fractions.
  254.   secs = parseInt( secs + .5 );
  255.   var hours = parseInt( secs/3600 );
  256.   secs -= hours*3600;
  257.   var mins = parseInt( secs/60 );
  258.   secs -= mins*60;
  259.   var result;
  260.   if ( hours )
  261.     result = getString( "longTimeFormat" );
  262.   else
  263.     result = getString( "shortTimeFormat" );
  264.  
  265.   if ( hours < 10 )
  266.      hours = "0" + hours;
  267.   if ( mins < 10 )
  268.      mins = "0" + mins;
  269.   if ( secs < 10 )
  270.      secs = "0" + secs;
  271.  
  272.   // Insert hours, minutes, and seconds into result string.
  273.   result = replaceInsert( result, 1, hours );
  274.   result = replaceInsert( result, 2, mins );
  275.   result = replaceInsert( result, 3, secs );
  276.  
  277.   return result;
  278. }
  279.  
  280. function loadDialog()
  281. {
  282.   var sourceUrlValue = {};
  283.   var initialDownloadTimeValue = {};
  284.   // targetFile is global because we are going to want re-use later one...
  285.   targetFile =  helperAppLoader.getDownloadInfo(sourceUrlValue, initialDownloadTimeValue);
  286.  
  287.   var sourceUrl = sourceUrlValue.value;
  288.   startTime = initialDownloadTimeValue.value / 1000;
  289.  
  290.   // set the elapsed time on the first pass...
  291.   var now = ( new Date() ).getTime();
  292.   // intialize the elapsed time global variable slot
  293.   elapsed = now - startTime;
  294.   // Update elapsed time display.
  295.   dialog.timeElapsed.setAttribute("value", formatSeconds( elapsed / 1000 ));
  296.   dialog.timeLeft.setAttribute("value", formatSeconds( 0 ));
  297.  
  298.   dialog.location.setAttribute("value", sourceUrl.spec );
  299.   dialog.fileName.setAttribute( "value", targetFile.unicodePath );
  300.  
  301.   var prefs = Components.classes[prefContractID].getService(Components.interfaces.nsIPref);
  302.   if (prefs)
  303.     keepProgressWindowUpBox.checked = prefs.GetBoolPref("browser.download.progressDnldDialog.keepAlive");
  304. }
  305.  
  306. function replaceInsert( text, index, value ) {
  307.    var result = text;
  308.    var regExp = new RegExp( "#"+index );
  309.    result = result.replace( regExp, value );
  310.    return result;
  311. }
  312.  
  313. function onLoad() {
  314.     // Set global variables.
  315.     helperAppLoader = window.arguments[0].QueryInterface( Components.interfaces.nsIHelperAppLauncher );
  316.  
  317.     if ( !helperAppLoader ) {
  318.         dump( "Invalid argument to downloadProgress.xul\n" );
  319.         window.close()
  320.         return;
  321.     }
  322.  
  323.     dialog = new Object;
  324.     dialog.strings = new Array;
  325.     dialog.location    = document.getElementById("dialog.location");
  326.     dialog.contentType = document.getElementById("dialog.contentType");
  327.     dialog.fileName    = document.getElementById("dialog.fileName");
  328.     dialog.status      = document.getElementById("dialog.status");
  329.     dialog.progress    = document.getElementById("dialog.progress");
  330.     dialog.progressText = document.getElementById("dialog.progressText");
  331.     dialog.timeLeft    = document.getElementById("dialog.timeLeft");
  332.     dialog.timeElapsed = document.getElementById("dialog.timeElapsed");
  333.     dialog.cancel      = document.getElementById("cancel");
  334.     dialog.pause       = document.getElementById("pause");
  335.     dialog.resume      = document.getElementById("resume");
  336.     dialog.pauseResumeDeck = document.getElementById("pauseResumeDeck");
  337.     dialog.request     = 0;
  338.     dialog.downloadPaused = false;
  339.     keepProgressWindowUpBox = document.getElementById('keepProgressDialogUp');
  340.  
  341.     // Set up dialog button callbacks.
  342.     var object = this;
  343.     doSetOKCancel("", function () { return object.onCancel();});
  344.  
  345.     // Fill dialog.
  346.     loadDialog();
  347.  
  348.     // set our web progress listener on the helper app launcher
  349.     helperAppLoader.setWebProgressListener(progressListener);
  350.  
  351.     if ( window.opener ) {
  352.         moveToAlertPosition();
  353.     } else {
  354.         centerWindowOnScreen();
  355.     }
  356. }
  357.  
  358. function onUnload()
  359. {
  360.  
  361.   // remember the user's decision for the checkbox.
  362.  
  363.   var prefs = Components.classes[prefContractID].getService(Components.interfaces.nsIPref);
  364.   if (prefs)
  365.     prefs.SetBoolPref("browser.download.progressDnldDialog.keepAlive", keepProgressWindowUpBox.checked);
  366.  
  367.    // Cancel app launcher.
  368.    if (helperAppLoader)
  369.    {
  370.      try
  371.      {
  372.        helperAppLoader.closeProgressWindow();
  373.        helperAppLoader = null;
  374.      }
  375.  
  376.      catch( exception ) {}
  377.    }
  378. }
  379.  
  380. // If the user presses cancel, tell the app launcher and close the dialog...
  381. function onCancel ()
  382. {
  383.    // Cancel app launcher.
  384.    if (helperAppLoader)
  385.    {
  386.      try
  387.      {
  388.        helperAppLoader.Cancel();
  389.      }
  390.  
  391.      catch( exception ) {}
  392.    }
  393.  
  394.   // Close up dialog by returning true.
  395.   return true;
  396. }
  397.  
  398. // closeWindow should only be called from processEndOfDownload
  399. function closeWindow()
  400. {
  401.   // while the time out was fired the user may have checked the
  402.   // keep this dialog open box...so we should abort and not actually
  403.   // close the window.
  404.  
  405.   if (!keepProgressWindowUpBox.checked)
  406.     window.close();
  407.   else
  408.     setupPostProgressUI();
  409. }
  410.  
  411. function setupPostProgressUI()
  412. {
  413.   //dialog.cancel.childNodes[0].nodeValue = "Close";
  414.   // turn the cancel button into a close button
  415.   var cancelButton = document.getElementById('cancel');
  416.   if (cancelButton)
  417.   {
  418.     cancelButton.label = getString("close");
  419.     cancelButton.setAttribute("onclick", "window.close()");
  420.   }
  421.  
  422.   // enable the open and open folder buttons
  423.   var openFolderButton = document.getElementById('openFolder');
  424.   var openButton = document.getElementById('open');
  425.  
  426.   openFolderButton.removeAttribute("disabled");
  427.   if ( !targetFile.isExecutable() )
  428.   {
  429.     openButton.removeAttribute("disabled");
  430.   }
  431.  
  432.   dialog.pause.disabled = true; // setAttribute("disabled", true);
  433.   dialog.resume.disabled = true;
  434.  
  435. }
  436.  
  437. // when we receive a stop notification we are done reporting progress on the download
  438. // now we have to decide if the window is supposed to go away or if we are supposed to remain open
  439. // and enable the open and open folder buttons on the dialog.
  440. function processEndOfDownload()
  441. {
  442.   if (!keepProgressWindowUpBox.checked)
  443.     closeWindow(); // shut down, we are all done.
  444.  
  445.   // o.t the user has asked the window to stay open so leave it open and enable the open and open new folder buttons
  446.   setupPostProgressUI();
  447. }
  448.  
  449. function doOpen()
  450. {
  451.   try {
  452.     var localFile = targetFile.QueryInterface(Components.interfaces.nsILocalFile);
  453.     if (localFile)
  454.       localFile.launch();
  455.   } catch (ex) {}
  456. }
  457.  
  458. function doOpenFolder()
  459. {
  460.   try {
  461.     var localFile = targetFile.QueryInterface(Components.interfaces.nsILocalFile);
  462.     if (localFile)
  463.       localFile.reveal();
  464.   } catch (ex) {}
  465. }
  466.  
  467. function doPauseButton() {
  468.     if (dialog.downloadPaused)
  469.     {
  470.         // resume
  471.         dialog.downloadPaused = false;
  472.         dialog.pauseResumeDeck.setAttribute("index", "1");
  473.         dialog.request.resume()
  474.     }
  475.     else
  476.     {
  477.         // suspend
  478.         dialog.downloadPaused = true;
  479.         dialog.pauseResumeDeck.setAttribute("index", "2");
  480.         dialog.request.suspend()
  481.     }
  482. }
  483.