home *** CD-ROM | disk | FTP | other *** search
/ Freelog 112 / FreelogNo112-NovembreDecembre2012.iso / Multimedia / Songbird / Songbird_2.0.0-2311_windows-i686-msvc8.exe / jsmodules / SBJobUtils.jsm < prev    next >
Text File  |  2012-06-08  |  10KB  |  328 lines

  1. /*
  2. //
  3. // BEGIN SONGBIRD GPL
  4. // 
  5. // This file is part of the Songbird web player.
  6. //
  7. // Copyright(c) 2005-2008 POTI, Inc.
  8. // http://songbirdnest.com
  9. // 
  10. // This file may be licensed under the terms of of the
  11. // GNU General Public License Version 2 (the "GPL").
  12. // 
  13. // Software distributed under the License is distributed 
  14. // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either 
  15. // express or implied. See the GPL for the specific language 
  16. // governing rights and limitations.
  17. //
  18. // You should have received a copy of the GPL along with this 
  19. // program. If not, go to http://www.gnu.org/licenses/gpl.html
  20. // or write to the Free Software Foundation, Inc., 
  21. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22. // 
  23. // END SONGBIRD GPL
  24. //
  25.  */
  26.  
  27. EXPORTED_SYMBOLS = [ "SBJobUtils" ];
  28.  
  29. // Amount of time to wait before launching a progress dialog
  30. const PROGRESS_DEFAULT_DIALOG_DELAY = 1000;
  31.  
  32. const Cc = Components.classes;
  33. const Ci = Components.interfaces;
  34. const Cr = Components.results;
  35. const Ce = Components.Exception;
  36. const Cu = Components.utils;
  37.  
  38. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  39. Cu.import("resource://app/jsmodules/ArrayConverter.jsm");
  40. Cu.import("resource://app/jsmodules/WindowUtils.jsm");
  41. Cu.import("resource://app/jsmodules/SBTimer.jsm");
  42.  
  43. /******************************************************************************
  44.  * A collection of functions for manipulating sbIJob* interfaces
  45.  *****************************************************************************/
  46. var SBJobUtils = {
  47.  
  48.   /**
  49.    * \brief Display a progress dialog for an object implementing sbIJobProgress.
  50.    *
  51.    * If the job has not completed in a given amount of time, display
  52.    * a modal progress dialog. 
  53.    *
  54.    * \param aJobProgress    sbIJobProgress interface to be displayed.
  55.    * \param aWindow         Parent window for the dialog. Can be null.
  56.    * \param aTimeout        Time to wait before opening a dialog. 
  57.    *                        Defaults to 1 second.  Pass 0 to open 
  58.    *                        the dialog immediately.
  59.    * \param aNonModal       if true the dialog is not modal
  60.    */
  61.   showProgressDialog: function(aJobProgress, aWindow, aTimeout, aNonModal) {
  62.     if (!(aJobProgress instanceof Ci.sbIJobProgress)) {
  63.       throw new Error("showProgressDialog requires an object implementing sbIJobProgress");
  64.     }
  65.  
  66.     function showDialog() {
  67.       if (timer) {
  68.         timer.cancel();
  69.         timer = null;
  70.       }
  71.       
  72.       // If the job is already complete, skip the dialog
  73.       if (aJobProgress.status == Ci.sbIJobProgress.STATUS_SUCCEEDED) {
  74.         return;
  75.       }
  76.      
  77.       // If the job is blocked and the dialog is modal, skip the dialog to avoid
  78.       // blocking the UI
  79.       if (!aNonModal && aJobProgress.blocked) {
  80.         return;
  81.       }
  82.  
  83.       // Parent to the main window by default
  84.       if (!aWindow || aWindow.closed) {
  85.         var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  86.                            .getService(Components.interfaces.nsIWindowMediator);
  87.         aWindow = wm.getMostRecentWindow("Songbird:Main");
  88.       }
  89.       WindowUtils.openDialog(
  90.         aWindow,
  91.          "chrome://songbird/content/xul/jobProgress.xul",
  92.          "job_progress_dialog",
  93.          "chrome,centerscreen",
  94.          !aNonModal,
  95.          [ aJobProgress ],
  96.          null,
  97.          null);
  98.     } 
  99.    
  100.     if (aTimeout == null) {
  101.       aTimeout = PROGRESS_DEFAULT_DIALOG_DELAY;
  102.     }
  103.     
  104.     var timer;
  105.     if (aTimeout) {
  106.       // Wait a bit before launching the dialog.  If the job is already
  107.       // complete don't bother launching it.
  108.       // The timer will maintain a ref to this closure during the delay, and vice versa.
  109.       timer = new SBTimer(showDialog, aTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
  110.     } else {
  111.       // If 0 just show immediately
  112.       showDialog();
  113.     }
  114.   }
  115.   
  116. }
  117.  
  118.  
  119. /******************************************************************************
  120.  * A base implementation of sbIJobProgress, to be extended
  121.  * when creating a JavaScript sbIJobProgress object.
  122.  *
  123.  * Supports forwarding progress information to a child sbIJobProgress,
  124.  * for cases where a main job needs to aggregate a number of sub-jobs.
  125.  *
  126.  * See DirectoryImportJob for an example.
  127.  *****************************************************************************/
  128. SBJobUtils.JobBase = function() {
  129.   this._errorMessages = [];
  130.   this._listeners = [];
  131. }
  132. SBJobUtils.JobBase.prototype = {
  133.   QueryInterface          : XPCOMUtils.generateQI(
  134.       [Ci.sbIJobProgress, Ci.sbIJobCancelable, 
  135.        Ci.sbIJobProgressListener, Ci.nsIClassInfo]),
  136.  
  137.   /** nsIClassInfo, so callers don't have to QI from JS **/
  138.   
  139.   classDescription        : 'Songbird Job Progress Implementation',
  140.   classID                 : null,
  141.   contractID              : null,
  142.   flags                   : Ci.nsIClassInfo.MAIN_THREAD_ONLY,
  143.   implementationLanguage  : Ci.nsIProgrammingLanguage.JAVASCRIPT,
  144.   getHelperForLanguage    : function(aLanguage) { return null; },
  145.   getInterfaces : function(count) {
  146.     var interfaces = [Ci.sbIJobProgress,
  147.                       Ci.sbIJobCancelable,
  148.                       Ci.sbIJobProgressListener,
  149.                       Ci.nsIClassInfo,
  150.                       Ci.nsISupports
  151.                      ];
  152.     count.value = interfaces.length;
  153.     return interfaces;
  154.   },
  155.  
  156.   
  157.   _status              : Ci.sbIJobProgress.STATUS_RUNNING,
  158.   _blocked             : false,
  159.   _statusText          : "",
  160.   _titleText           : "",
  161.   _progress            : 0,
  162.   _total               : 0,
  163.   
  164.   // Array of error strings
  165.   _errorMessages       : null,
  166.   
  167.   // Array of listeners
  168.   _listeners           : null,
  169.   
  170.   // Another sbIJobProgress. If set, all sbIJobProgress calls other than
  171.   // status and listeners will be forwarded through to the other job.
  172.   // This can be used to provide a single interface that aggregates
  173.   // several sub-jobs.
  174.   _jobProgressDelegate : null,
  175.   
  176.   
  177.   /** sbIJobProgress **/
  178.   
  179.   get status() {
  180.     // Note that status is not delegated, as the main job only completes
  181.     // when all sub-jobs are finished.
  182.     return this._status;
  183.   },
  184.   
  185.   get blocked() {
  186.     return (this._jobProgressDelegate) ?
  187.       this._jobProgressDelegate.blocked : this._blocked;
  188.   },
  189.  
  190.   get statusText() {
  191.     return (this._jobProgressDelegate) ? 
  192.       this._jobProgressDelegate.statusText : this._statusText;
  193.   },
  194.   
  195.   get titleText() {
  196.     return (this._jobProgressDelegate) ? 
  197.       this._jobProgressDelegate.titleText : this._titleText;
  198.   },
  199.   
  200.   get progress() {
  201.     return (this._jobProgressDelegate) ? 
  202.       this._jobProgressDelegate.progress : this._progress;
  203.   },
  204.   
  205.   get total() {
  206.     return (this._jobProgressDelegate) ? 
  207.       this._jobProgressDelegate.total : this._total;
  208.   },
  209.   
  210.   get errorCount() {
  211.     return (this._jobProgressDelegate) ? 
  212.       this._jobProgressDelegate.errorCount : this._errorMessages.length;
  213.   },
  214.   
  215.   getErrorMessages: function Job_getErrorMessages() {
  216.     return (this._jobProgressDelegate) ? 
  217.       this._jobProgressDelegate.getErrorMessages() :
  218.       ArrayConverter.enumerator(this._errorMessages);
  219.   },
  220.   
  221.   addJobProgressListener: function Job_addJobProgressListener(aListener) {
  222.     aListener.QueryInterface(Ci.sbIJobProgressListener);
  223.     this._listeners.push(aListener);
  224.   },
  225.   
  226.   removeJobProgressListener: function Job_removeJobProgressListener(aListener){
  227.     var index = this._listeners.indexOf(aListener);
  228.     if (index > -1) {
  229.       this._listeners.splice(index,1);
  230.     }
  231.   },
  232.   
  233.   
  234.   /** sbIJobCancelable **/
  235.   
  236.   _canCancel: false,
  237.   get canCancel() {
  238.     return (this._jobProgressDelegate && 
  239.             this._jobProgressDelegate instanceof Ci.sbIJobCancelable) ? 
  240.               this._jobProgressDelegate.canCancel : this._canCancel;
  241.   },
  242.   
  243.   cancel: function Job_cancel() {
  244.     // Override this method
  245.     throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  246.   },
  247.   
  248.   
  249.   /** Non-interface methods **/
  250.   
  251.   /**
  252.    * Delegate most of sbIJobProgress to the given sub-job.
  253.    * Allows this job to wrap/aggregate other jobs.
  254.    * Pass null to stop delegation.
  255.    */
  256.   delegateJobProgress: function Job_delegateJobProgress(aJob)  {
  257.     if (aJob != null && !(aJob.QueryInterface(Ci.sbIJobProgress))) {
  258.       throw Components.results.NS_ERROR_INVALID_ARG;
  259.     }
  260.     
  261.     if (this._jobProgressDelegate) {
  262.       this._jobProgressDelegate.removeJobProgressListener(this);
  263.     }
  264.     
  265.     this._jobProgressDelegate = aJob;
  266.     
  267.     if (this._jobProgressDelegate) {
  268.       this._jobProgressDelegate.addJobProgressListener(this);
  269.     }
  270.   },
  271.  
  272.  
  273.   /**
  274.    * sbIJobProgressListener implementation. Called by 
  275.    * _jobProgressDelegate if set.
  276.    */
  277.   onJobProgress: function Job_onJobProgress(aJob) {
  278.     try {
  279.         if ((!this._jobProgressDelegate) || this._jobProgressDelegate != aJob) {
  280.           // Just report the error. Don't throw, as that would just go to the
  281.           // sub-job, and wouldn't help.
  282.           Cu.reportError("Job_onJobProgress called with invalid _jobProgressDelegate state!");
  283.         }
  284.         
  285.         // Forward the progress notification on to all our listeners
  286.         this.notifyJobProgressListeners();
  287.         
  288.         // If the delegate is done, allow the main job to move on
  289.         if (this._jobProgressDelegate.status != Ci.sbIJobProgress.STATUS_RUNNING) {
  290.           this.onJobDelegateCompleted();
  291.         }
  292.      }
  293.      catch (e) {
  294.        Cu.reportError(e);
  295.      }
  296.   },
  297.   
  298.   
  299.   /**
  300.    * Called when a sub-job (set with delegateJobProgress) completes.
  301.    * Override this method to carry on with other work.
  302.    */
  303.   onJobDelegateCompleted: function Job_onJobDelegateCompleted() {
  304.     // Base behaviour is to just throw away the delegated job
  305.     this.delegateJobProgress(null);
  306.   },
  307.  
  308.  
  309.   /**
  310.    * Poke listeners and tell them to check the current progress
  311.    */  
  312.   notifyJobProgressListeners: function Job_notifyJobProgressListeners() {
  313.     var thisJob = this;
  314.     // need to clone the array, otherwise removing one in the middle gets
  315.     // things confused
  316.     var listeners = [].concat(this._listeners);
  317.     listeners.forEach( function (listener) {
  318.       try {
  319.         listener.onJobProgress(thisJob);
  320.       } catch (e) {
  321.         Cu.reportError(e);
  322.       }
  323.     });
  324.   }
  325. }
  326.  
  327.  
  328.