home *** CD-ROM | disk | FTP | other *** search
/ Freelog 112 / FreelogNo112-NovembreDecembre2012.iso / Multimedia / Songbird / Songbird_2.0.0-2311_windows-i686-msvc8.exe / components / sbDeviceFirmwareAutoCheckForUpdate.js < prev    next >
Text File  |  2012-06-08  |  17KB  |  473 lines

  1. /*
  2.  *=BEGIN SONGBIRD GPL
  3.  *
  4.  * This file is part of the Songbird web player.
  5.  *
  6.  * Copyright(c) 2005-2010 POTI, Inc.
  7.  * http://www.songbirdnest.com
  8.  *
  9.  * This file may be licensed under the terms of of the
  10.  * GNU General Public License Version 2 (the ``GPL'').
  11.  *
  12.  * Software distributed under the License is distributed
  13.  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
  14.  * express or implied. See the GPL for the specific language
  15.  * governing rights and limitations.
  16.  *
  17.  * You should have received a copy of the GPL along with this
  18.  * program. If not, go to http://www.gnu.org/licenses/gpl.html
  19.  * or write to the Free Software Foundation, Inc.,
  20.  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21.  *
  22.  *=END SONGBIRD GPL
  23.  */
  24.  
  25. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  26. Components.utils.import("resource://app/jsmodules/SBDataRemoteUtils.jsm");
  27. Components.utils.import("resource://app/jsmodules/SBTimer.jsm");
  28. Components.utils.import("resource://app/jsmodules/SBUtils.jsm");
  29. Components.utils.import("resource://app/jsmodules/StringUtils.jsm");
  30. Components.utils.import("resource://app/jsmodules/WindowUtils.jsm");
  31.  
  32. const Ci = Components.interfaces;
  33. const Cc = Components.classes;
  34. const Cr = Components.results;
  35. const Cu = Components.utils;
  36.  
  37. const NS_QUIT_APPLICATION_GRANTED_TOPIC = "quit-application-granted";
  38. const NS_TIMER_CALLBACK_TOPIC           = "timer-callback";
  39. const SB_FINAL_UI_STARTUP_TOPIC         = "final-ui-startup";
  40. const SB_TIMER_MANAGER_PREFIX           = "songbird-device-firmware-update-";
  41.  
  42. const FIRMWARE_WIZARD_ACTIVE_DATAREMOTE = "firmware.wizard.active";
  43.  
  44. const FIRMWARE_UPDATE_INTERVAL = "songbird.firmware.update.defaultInterval";
  45.  
  46. function DEBUG(msg) {
  47.   return;
  48.  
  49.   function repr(x) {
  50.     if (typeof(x) == "undefined") {
  51.       return 'undefined';
  52.     } else if (x == null) {
  53.       return 'null';
  54.     } else if (typeof x == 'function') {
  55.       return x.name+'(...)';
  56.     } else if (typeof x == 'string') {
  57.       return x.toSource().match(/^\(new String\((.*)\)\)$/)[1];
  58.     } else if (typeof x == 'number') {
  59.       return x.toSource().match(/^\(new Number\((.*)\)\)$/)[1];
  60.     } else if (typeof x == 'object' && x instanceof Array) {
  61.       var value = '';
  62.       for (var i=0; i<x.length; i++) {
  63.         if (i) value = value + ', ';
  64.         value = value + repr(x[i]);
  65.       }
  66.       return '['+value+']';
  67.     } else if (x instanceof Ci.nsISupports) {
  68.       return x.toString();
  69.     } else {
  70.       return x.toSource();
  71.     }
  72.   }
  73.   var fullMsg = 'sbDeviceFirmwareAutocheckForUpdate:: '+DEBUG.caller.name;
  74.   if (typeof(msg) == "undefined") {
  75.     // when nothing is passed in, print the arguments
  76.     fullMsg += '(';
  77.     for (var i=0; i<DEBUG.caller.length; i++) {
  78.       if (i) fullMsg += ', ';
  79.       fullMsg += repr(DEBUG.caller.arguments[i]);
  80.     }
  81.     fullMsg += ')';
  82.   } else {
  83.     fullMsg += ': ';
  84.     if (typeof msg != 'object' || msg instanceof Array) {
  85.       fullMsg += repr(msg);
  86.     } else {
  87.       fullMsg += msg.toSource();
  88.     }
  89.   }
  90.   fullMsg += '\n';
  91.   
  92.   Cu.reportError(fullMsg);
  93. }
  94.  
  95.  
  96. function sbDeviceFirmwareAutoCheckForUpdate() {
  97.   DEBUG();
  98.  
  99.   var obs = Cc["@mozilla.org/observer-service;1"]
  100.               .getService(Ci.nsIObserverService);
  101.   obs.addObserver(this, SB_FINAL_UI_STARTUP_TOPIC, false);
  102. }
  103.  
  104. /** a cached reference to the device firmware update service */
  105. sbDeviceFirmwareAutoCheckForUpdate.prototype._deviceFirmwareUpdater = null;
  106. /** a cached reference to the device manager service */
  107. sbDeviceFirmwareAutoCheckForUpdate.prototype._deviceManager = null;
  108. /** a set where the keys are the ids of devices that have registered timers */
  109. sbDeviceFirmwareAutoCheckForUpdate.prototype._registeredDevices = {};
  110. /** the queue of devices currently needing a firmware update check */
  111. sbDeviceFirmwareAutoCheckForUpdate.prototype._queue = [];
  112. /** the device currenly being checked for a firmware update */
  113. sbDeviceFirmwareAutoCheckForUpdate.prototype._queueItem = null;
  114. /** whether the current item in the queue has been successfully checked */
  115. sbDeviceFirmwareAutoCheckForUpdate.prototype._queueItemSuccess = false;
  116. /** timer used to manage firmware update queue */
  117. sbDeviceFirmwareAutoCheckForUpdate.prototype._timer = null;
  118. /** the timer manager service (long-running timer service) */
  119. sbDeviceFirmwareAutoCheckForUpdate.prototype._timerManager = null;
  120.  
  121. sbDeviceFirmwareAutoCheckForUpdate.prototype.classDescription =
  122.     'Songbird Device Firmware Auto Check For Update';
  123. sbDeviceFirmwareAutoCheckForUpdate.prototype.classID =
  124.     Components.ID("{2137a87f-2ade-448b-a093-bad4f6649fa3}");
  125. sbDeviceFirmwareAutoCheckForUpdate.prototype.contractID =
  126.     '@songbirdnest.com/Songbird/Device/Firmware/AutoCheckForUpdate;1';
  127. sbDeviceFirmwareAutoCheckForUpdate.prototype.flags = Ci.nsIClassInfo.SINGLETON;
  128. sbDeviceFirmwareAutoCheckForUpdate.prototype.interfaces =
  129.     [Ci.nsISupports, Ci.nsIClassInfo, Ci.nsIObserver, Ci.sbIDeviceEventListener];
  130. sbDeviceFirmwareAutoCheckForUpdate.prototype.getHelperForLanguage = Function();
  131. sbDeviceFirmwareAutoCheckForUpdate.prototype.getInterfaces =
  132. function sbDeviceFirmwareAutoCheckForUpdate_getInterfaces(count) {
  133.   count.value = this.interfaces.length;
  134.   return this.interfaces;
  135. }
  136. sbDeviceFirmwareAutoCheckForUpdate.prototype.QueryInterface =
  137.     XPCOMUtils.generateQI(sbDeviceFirmwareAutoCheckForUpdate.prototype.interfaces);
  138.  
  139. /** nsIObserver */
  140. sbDeviceFirmwareAutoCheckForUpdate.prototype.observe =
  141. function sbDeviceFirmwareAutoCheckForUpdate_observe(subject, topic, data) {
  142.   DEBUG();
  143.  
  144.   var obs = Cc["@mozilla.org/observer-service;1"]
  145.               .getService(Ci.nsIObserverService);
  146.  
  147.   if (topic == SB_FINAL_UI_STARTUP_TOPIC) {
  148.     obs.removeObserver(this, SB_FINAL_UI_STARTUP_TOPIC);
  149.     obs.addObserver(this, NS_QUIT_APPLICATION_GRANTED_TOPIC, false);
  150.  
  151.     this._deviceFirmwareUpdater = 
  152.       Cc['@songbirdnest.com/Songbird/Device/Firmware/Updater;1']
  153.         .getService(Ci.sbIDeviceFirmwareUpdater);
  154.         
  155.     this._deviceManager =
  156.       Cc['@songbirdnest.com/Songbird/DeviceManager;2']
  157.         .getService(Ci.sbIDeviceManager2);
  158.         
  159.     this._deviceManager.addEventListener(this);
  160.     
  161.   } else if (topic == NS_QUIT_APPLICATION_GRANTED_TOPIC) {
  162.     // cleanup
  163.     obs.removeObserver(this, NS_QUIT_APPLICATION_GRANTED_TOPIC);
  164.  
  165.     if(this._deviceManager) {
  166.       this._deviceManager.removeEventListener(this);
  167.     }
  168.     
  169.     if (this._timer) {
  170.       this._clearTimer();
  171.     }
  172.  
  173.     if (this._timerManager) {
  174.       for (let id in this._registeredDevices) {
  175.         this._unregisterTimer(id);
  176.       }
  177.     }
  178.  
  179.     if (this._queueItem && this._deviceFirmwareUpdater) {
  180.       this._deviceFirmwareUpdater.finalizeUpdate(this._queueItem);
  181.     }
  182.  
  183.   } else if (topic == NS_TIMER_CALLBACK_TOPIC) {
  184.     DEBUG(this._queue.length + " items, top is " + this._queueItem);
  185.     if(this._queue.length &&
  186.        !this._queueItem) {
  187.       // Queue has items in it and we're not currently processing an item.
  188.       // Grab first device in the queue.
  189.       let device = this._queue[0];
  190.       this._queueItem = device;
  191.       // Check for update
  192.       if (device.getPreference("firmware.update.enabled")) {
  193.         try {
  194.           this._deviceFirmwareUpdater.checkForUpdate(device, 0, 0, this);
  195.         }
  196.         catch (e) {
  197.           Cu.reportError(e);
  198.         }
  199.       }
  200.     }
  201.     else if(this._queueItem && 
  202.             this._queueItemSuccess) {
  203.       // If the device is busy, wait for the next timer callback.
  204.       if(this._queueItem.isBusy) {
  205.         return;
  206.       }
  207.       
  208.       this._deviceFirmwareUpdater.finalizeUpdate(this._queueItem);
  209.       
  210.       let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
  211.                  .getService(Ci.nsIWindowMediator);
  212.       let parent = wm.getMostRecentWindow("Songbird:Main");
  213.  
  214.       WindowUtils.openModalDialog
  215.         (parent,
  216.          "chrome://songbird/content/xul/device/deviceFirmwareWizard.xul",
  217.          "device_firmware_dialog",
  218.          "",
  219.          ["", "defaultDevice=false", this._queueItem ],
  220.          null);
  221.  
  222.       this._queue.splice(0, 1);
  223.       this._queueItem = null;
  224.       this._queueItemSuccess = false;
  225.     }
  226.     else if(!this._queue.length &&
  227.             this._timer) {
  228.       // Queue is empty, clear timer.
  229.       this._timer.cancel();
  230.       this._timer = null;
  231.     }
  232.   }
  233. }
  234.  
  235. sbDeviceFirmwareAutoCheckForUpdate.prototype.notify =
  236. function sbDeviceFirmwareAutoCheckForUpdate_notify(aDevice) {
  237.   DEBUG();
  238.   if (!this._timer) {
  239.     // set up the timer
  240.     this._timer = Cc['@mozilla.org/timer;1'].createInstance(Ci.nsITimer);
  241.     this._timer.init(this, 15000, Ci.nsITimer.TYPE_REPEATING_SLACK);
  242.   }
  243.   if (this._queue.indexOf(aDevice) < 0) {
  244.     this._queue.push(aDevice);
  245.   }
  246. }
  247.  
  248. /** sbIDeviceEventListener */
  249. sbDeviceFirmwareAutoCheckForUpdate.prototype.onDeviceEvent =
  250. function sbDeviceFirmwareAutoCheckForUpdate_onDeviceEvent(aEvent) {
  251.   DEBUG();
  252.   var device = null;
  253.  
  254.   switch(aEvent.type) {
  255.     case Ci.sbIDeviceEvent.EVENT_DEVICE_ADDED: {
  256.       device = aEvent.data.QueryInterface(Ci.sbIDevice);
  257.       if (device.getPreference("firmware.update.enabled")) {
  258.         this._registerTimer(device);
  259.       }
  260.       
  261.       //
  262.       // If it's the first time the device is connected, check
  263.       // for a firmware update right away. We also set the 
  264.       // auto check for firmware update pref to true.  Since
  265.       // we only do this the first time the device is connected
  266.       // the user can choose not to do this and their preference
  267.       // will be respected. This is conditional on there being a
  268.       // firmware handler that can handle updating firmware for
  269.       // the device.
  270.       //
  271.       // Check to see if the device is in recoveryMode. If it is
  272.       // we do not enable automatic checks for firmware updates.
  273.       // 
  274.       var hasHandler = this._deviceFirmwareUpdater.hasHandler(device, 0, 0);
  275.       var recoveryMode = false;
  276.       if (hasHandler) {
  277.         let handler = this._deviceFirmwareUpdater.getHandler(device, 0, 0);
  278.         handler.bind(device, null);
  279.         recoveryMode = handler.recoveryMode;
  280.         handler.unbind();
  281.       }
  282.         
  283.       if (device.getPreference("firstTime") && 
  284.           hasHandler &&
  285.           !recoveryMode &&
  286.           this._queue.indexOf(device) < 0) {
  287.         device.setPreference("firmware.update.enabled", true);
  288.         this._queue.push(device);
  289.         if (!this._timer) {
  290.           // set up the timer, when it's the first time, we wait 15 seconds in
  291.           // the hopes that the device will have finished mounting before
  292.           // we check for a firmware update.
  293.           this._timer = Cc['@mozilla.org/timer;1'].createInstance(Ci.nsITimer);
  294.           this._timer.init(this, 15000, Ci.nsITimer.TYPE_REPEATING_SLACK);
  295.         }
  296.       }
  297.       
  298.       // XXXAus says:
  299.       //
  300.       // Disabled this for now since we did not update the UE
  301.       // to consider the Tools menu entry for repairing devices.
  302.       //
  303.       
  304.       /*
  305.       // if we have a firmware handler for this device, we'll
  306.       // also check to see if it's recovery mode and ask the 
  307.       // user if they wish to repair it if it is.
  308.       if (this._deviceFirmwareUpdater.hasHandler(device, 0, 0) &&
  309.           !SBDataGetBoolValue(FIRMWARE_WIZARD_ACTIVE_DATAREMOTE)) {
  310.         var handler = this._deviceFirmwareUpdater.getHandler(device, 0, 0);
  311.         handler.bind(device, null);
  312.         
  313.         var recoveryMode = handler.recoveryMode;
  314.         handler.unbind();
  315.         
  316.         // Also check to make sure we're not currently updating
  317.         // other firmware, if so, don't do anything for this device
  318.         if (recoveryMode) {
  319.           var self = this;
  320.           SBUtils.deferFunction(
  321.             function() { 
  322.               self._promptForRepair(device); 
  323.             });
  324.         }
  325.       }
  326.       */
  327.     }
  328.     break;
  329.  
  330.     case Ci.sbIDeviceEvent.EVENT_DEVICE_REMOVED: {
  331.       // Device removed, if in queue, remove it, also finalize any update attempt.
  332.       device = aEvent.data.QueryInterface(Ci.sbIDevice);
  333.       this._unregisterTimer(device);
  334.       let index = this._queue.indexOf(device);
  335.       if (index < 0) {
  336.         break;
  337.       }
  338.       this._queue.splice(index, 1);
  339.       if(this._queueItem == device) {
  340.         // currently attempting this item
  341.         this._deviceFirmwareUpdater.finalizeUpdate(this._queueItem);
  342.         this._queueItem = null;
  343.         this._queueItemSuccess = false;
  344.       }
  345.     }
  346.     break;
  347.  
  348.     case Ci.sbIDeviceEvent.EVENT_DEVICE_PREFS_CHANGED: {
  349.       device = aEvent.origin.QueryInterface(Ci.sbIDevice);
  350.       if (device.getPreference("firmware.update.enabled")) {
  351.         this._registerTimer(device);
  352.       } else {
  353.         this._unregisterTimer(device);
  354.       }
  355.     }
  356.     break;
  357.  
  358.     case Ci.sbIDeviceEvent.EVENT_FIRMWARE_CFU_END: {
  359.       this._queueItemSuccess = aEvent.data;
  360.     }
  361.     break;
  362.     
  363.     case Ci.sbIDeviceEvent.EVENT_FIRMWARE_CFU_ERROR: {
  364.       // Remove from queue
  365.       device = aEvent.origin.QueryInterface(Ci.sbIDevice);
  366.       let index = this._queue.indexOf(device);
  367.       if(index < 0) {
  368.         break;
  369.       }
  370.       this._queue.splice(index, 1);
  371.       
  372.       if(this._queueItem == device) {
  373.         this._deviceFirmwareUpdater.finalizeUpdate(this._queueItem);
  374.         this._queueItem = null;
  375.         this._queueItemSuccess = false;
  376.       }
  377.     }
  378.     break;
  379.   }
  380. }
  381.  
  382. /**
  383.  * Registers a device with the timer manager
  384.  */
  385. sbDeviceFirmwareAutoCheckForUpdate.prototype._registerTimer =
  386. function sbDeviceFirmwareAutoCheckForUpdate__registerTimer(aDevice) {
  387.   DEBUG();
  388.   if (!this._timerManager) {
  389.     this._timerManager = Cc['@mozilla.org/updates/timer-manager;1']
  390.                            .getService(Ci.nsIUpdateTimerManager);
  391.   }
  392.   let self = this;
  393.   let callback = function(aTimer) {
  394.     self.notify(aDevice);
  395.   };
  396.   let interval = aDevice.getPreference("firmware.update.interval");
  397.   if (!interval) {
  398.     var prefs = Cc["@mozilla.org/fuel/application;1"]
  399.                   .getService(Ci.fuelIApplication)
  400.                   .prefs;
  401.     // Every 7 days in case there is no pref available.
  402.     interval = prefs.getValue(FIRMWARE_UPDATE_INTERVAL, 60 * 60 * 24 * 7);
  403.  
  404.     DEBUG("Using default interval for firmware update check: " + 
  405.           interval);
  406.   }
  407.   this._timerManager.registerTimer(SB_TIMER_MANAGER_PREFIX + aDevice.id,
  408.                                    callback,
  409.                                    interval);
  410.   this._registeredDevices[aDevice.id] = true;
  411. }
  412. /**
  413.  * Unegisters a with the timer manager for the given device
  414.  */
  415. sbDeviceFirmwareAutoCheckForUpdate.prototype._unregisterTimer =
  416. function sbDeviceFirmwareAutoCheckForUpdate__unregisterTimer(aDevice) {
  417.   DEBUG();
  418.   let id = aDevice;
  419.   if ("id" in aDevice) {
  420.     id = aDevice.id;
  421.   }
  422.   if (!this._registeredDevices[id]) {
  423.     // this device was never registerd. probably means update was disabled.
  424.     return;
  425.   }
  426.   delete this._registeredDevices[id];
  427.   // we can't actually unregister timers; instead, we can register it for
  428.   // a really long time (here, 136 years) and hope it doesn't get called
  429.   if (this._timerManager) {
  430.     this._timerManager.registerTimer(SB_TIMER_MANAGER_PREFIX + id,
  431.                                      null,
  432.                                      -1);
  433.   }
  434. }
  435.  
  436. sbDeviceFirmwareAutoCheckForUpdate.prototype._promptForRepair = 
  437. function sbDeviceFirmwareAutoCheckForUpdate__promptForRepair(aDevice) {
  438.   var windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"]
  439.                          .getService(Ci.nsIWindowMediator);
  440.   var songbirdWindow = windowMediator.getMostRecentWindow("Songbird:Main");  
  441.  
  442.   var prompter = Cc['@songbirdnest.com/Songbird/Prompter;1']
  443.                    .getService(Components.interfaces.sbIPrompter);
  444.   var confirmed = 
  445.     prompter.confirm(songbirdWindow,
  446.                      SBString('device.firmware.corrupt.title'),
  447.                      SBFormattedString('device.firmware.corrupt.message',
  448.                      [aDevice.name]));
  449.   if (confirmed) {
  450.     WindowUtils.openModalDialog
  451.                 (songbirdWindow,
  452.                  "chrome://songbird/content/xul/device/deviceFirmwareWizard.xul",
  453.                  "device_firmware_dialog",
  454.                  "",
  455.                  [ "mode=repair", "defaultDevice=false", aDevice ],
  456.                  null);  
  457.   }
  458. }
  459.  
  460. var NSGetModule = XPCOMUtils.generateNSGetModule(
  461.   [
  462.     sbDeviceFirmwareAutoCheckForUpdate,
  463.   ],
  464.   function(aCompMgr, aFileSpec, aLocation) {
  465.     XPCOMUtils.categoryManager.addCategoryEntry(
  466.       "app-startup",
  467.       sbDeviceFirmwareAutoCheckForUpdate.prototype.classDescription,
  468.       "service," + sbDeviceFirmwareAutoCheckForUpdate.prototype.contractID,
  469.       true,
  470.       true);
  471.   }
  472. );
  473.