addOnBundleInstaller.js
Go to the documentation of this file.
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4 //
5 // BEGIN SONGBIRD GPL
6 //
7 // This file is part of the Songbird web player.
8 //
9 // Copyright(c) 2005-2008 POTI, Inc.
10 // http://songbirdnest.com
11 //
12 // This file may be licensed under the terms of of the
13 // GNU General Public License Version 2 (the "GPL").
14 //
15 // Software distributed under the License is distributed
16 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
17 // express or implied. See the GPL for the specific language
18 // governing rights and limitations.
19 //
20 // You should have received a copy of the GPL along with this
21 // program. If not, go to http://www.gnu.org/licenses/gpl.html
22 // or write to the Free Software Foundation, Inc.,
23 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 //
25 // END SONGBIRD GPL
26 //
27  */
28 
34 //------------------------------------------------------------------------------
35 //------------------------------------------------------------------------------
36 //
37 // Add-on bundle installer widget services.
38 //
39 //------------------------------------------------------------------------------
40 //------------------------------------------------------------------------------
41 
42 //------------------------------------------------------------------------------
43 //
44 // Add-on bundle installer widget services defs.
45 //
46 //------------------------------------------------------------------------------
47 
48 // Component manager defs.
49 if (typeof(Cc) == "undefined")
50  var Cc = Components.classes;
51 if (typeof(Ci) == "undefined")
52  var Ci = Components.interfaces;
53 if (typeof(Cr) == "undefined")
54  var Cr = Components.results;
55 if (typeof(Cu) == "undefined")
56  var Cu = Components.utils;
57 
58 
59 //------------------------------------------------------------------------------
60 //
61 // Add-on bundle installer widget services.
62 //
63 //------------------------------------------------------------------------------
64 
72 function addOnBundleInstallerSvc(aWidget) {
73  this._widget = aWidget;
74 }
75 
76 // Define the object.
77 addOnBundleInstallerSvc.prototype = {
78  // Set the constructor.
80 
81  //
82  // Public widget services fields.
83  //
84  // restartRequired True if add-on installation requires a restart.
85  //
86 
87  restartRequired: false,
88 
89 
90  //
91  // Internal widget services fields.
92  //
93  // _widget First-run wizard add-ons widget.
94  // _addOnBundle Add-on bundle object.
95  // _addOnInstallList List of add-ons to install.
96  // _nextAddOnToInstall Index within _addOnInstallList of next add-on to
97  // install.
98  // _addOnFileDownloader File downloader for add-on.
99  //
100 
101  _widget: null,
102  _addOnBundle: null,
103  _addOnInstallList: null,
104  _nextAddOnToInstall: 0,
105  _addOnFileDownloader: null,
106 
107 
108  //----------------------------------------------------------------------------
109  //
110  // Widget services.
111  //
112  //----------------------------------------------------------------------------
113 
118  initialize: function addOnBundleInstallerSvc_initialize() {
119  },
120 
121 
126  finalize: function addOnBundleInstallerSvc_finalize() {
127  // Finalize the add-on file downloader.
128  if (this._addOnFileDownloader) {
129  this._addOnFileDownloader.listener = null;
130  this._addOnFileDownloader.cancel();
131  this._addOnFileDownloader = null;
132  }
133 
134  // Clear object fields.
135  this._widget = null;
136  this._addOnBundle = null;
137  this._addOnInstallList = null;
138  },
139 
140 
147  install: function addOnBundleInstallerSvc_install(aAddOnBundle) {
148  // Set the add-on bundle to install.
149  this._addOnBundle = aAddOnBundle;
150 
151  // Get the list of add-ons to install.
152  this._addOnInstallList = [];
153  var extensionCount = this._addOnBundle.bundleExtensionCount;
154  for (var i = 0; i < extensionCount; i++) {
155  if (this._addOnBundle.getExtensionInstallFlag(i)) {
156  var installInfo = { index: i, failed: false };
157  this._addOnInstallList.push(installInfo);
158  }
159  }
160 
161  // Start downloading the add-ons.
162  this._downloadNextAddOnStart();
163  },
164 
165 
170  cancel: function addOnBundleInstallerSvc_cancel() {
171  if (this._addOnFileDownloader) {
172  this._addOnFileDownloader.listener = null;
173  this._addOnFileDownloader.cancel();
174  this._addOnFileDownloader = null;
175  }
176  },
177 
178 
179  //----------------------------------------------------------------------------
180  //
181  // Widget nsIFileDownloaderListener services.
182  //
183  //----------------------------------------------------------------------------
184 
189  onProgress: function addOnBundleInstallerSvc_onProgress() {
190  // Update the UI.
191  this._update();
192  },
193 
194 
199  onComplete: function addOnBundleInstallerSvc_onComplete() {
200  // Update the UI.
201  this._update();
202 
203  // Complete downloading of next add-on.
204  this._downloadNextAddOnComplete();
205  },
206 
207 
208  //----------------------------------------------------------------------------
209  //
210  // Internal widget services.
211  //
212  //----------------------------------------------------------------------------
213 
218  _update: function addOnBundleInstallerSvc__update() {
219  // Get the current add-on index.
220  var currentAddOnIndex =
221  this._addOnInstallList[this._nextAddOnToInstall].index;
222 
223  // Set the current add-on name.
224  var currentAddOnLabelElem = this._getElement("current_add_on_label");
225  currentAddOnLabelElem.value =
226  this._addOnBundle.getExtensionAttribute(currentAddOnIndex, "name");
227 
228  // Set the total progress label.
229  var totalProgressLabelElem = this._getElement("total_progress_label");
230  totalProgressLabelElem.value =
231  SBFormattedString("add_on_bundle_installer.progress_all",
232  [ this._nextAddOnToInstall + 1,
233  this._addOnInstallList.length ]);
234 
235  // Set the current add-on download progress meter.
236  var progressMeterElem = this._getElement("progressmeter");
237  if (this._addOnFileDownloader)
238  progressMeterElem.value = this._addOnFileDownloader.percentComplete;
239  else
240  progressMeterElem.value = 0;
241  },
242 
243 
248  _downloadNextAddOnStart:
249  function addOnBundleInstallerSvc__downloadNextAddOnStart() {
250  // If all add-ons have been downloaded, install them all.
251  if (this._nextAddOnToInstall == this._addOnInstallList.length) {
252  this._installAllAddOns();
253  return;
254  }
255 
256  // Get the index of the next add-on to install.
257  var nextAddOnIndex =
258  this._addOnInstallList[this._nextAddOnToInstall].index;
259 
260  // Create an add-on file downloader.
261  this._addOnFileDownloader =
262  Cc["@songbirdnest.com/Songbird/FileDownloader;1"]
263  .createInstance(Ci.sbIFileDownloader);
264  this._addOnFileDownloader.listener = this;
265  this._addOnFileDownloader.sourceURISpec =
266  this._addOnBundle.getExtensionAttribute(nextAddOnIndex, "url");
267  this._addOnFileDownloader.destinationFileExtension = "xpi";
268 
269  // Start downloading add-on.
270  this._addOnFileDownloader.start();
271 
272  // Update the UI.
273  this._update();
274  },
275 
276 
281  _downloadNextAddOnComplete:
282  function addOnBundleInstallerSvc__downloadNextAddOnComplete() {
283  // Add downloaded file to the add-on install list.
284  var installInfo = this._addOnInstallList[this._nextAddOnToInstall];
285  if (this._addOnFileDownloader.succeeded)
286  installInfo.file = this._addOnFileDownloader.destinationFile;
287  else
288  installInfo.failed = true;
289  this._addOnFileDownloader.listener = null;
290  this._addOnFileDownloader = null;
291 
292  // Start download of the next add-on.
293  this._nextAddOnToInstall++;
294  this._downloadNextAddOnStart();
295  },
296 
297 
302  _installAllAddOns: function addOnBundleInstallerSvc__installAddOns() {
303  // Install all of the add-ons.
304  for (var i = 0; i < this._addOnInstallList.length; i++) {
305  var installInfo = this._addOnInstallList[i];
306  if (!installInfo.failed)
307  this._installAddOnFile(installInfo);
308  }
309 
310  // Present any add-on install errors.
311  this._widget.errorCount = this._presentErrors();
312 
313  // Post an install completion event.
314  var event = document.createEvent("Events");
315  event.initEvent("complete", true, true);
316  this._widget.dispatchEvent(event);
317  },
318 
319 
326  _installAddOnFile:
327  function addOnBundleInstallerSvc__installAddOnFile(aInstallInfo) {
328  // Ensure an add-on file was downloaded.
329  if (!aInstallInfo.file) {
330  aInstallInfo.failed = true;
331  return;
332  }
333 
334  // Get the extension manager.
335  var extensionManager = Cc["@mozilla.org/extensions/manager;1"]
336  .getService(Ci.nsIExtensionManager);
337 
338  // Install the add-on.
339  try {
340  extensionManager.installItemFromFile(aInstallInfo.file, "app-profile");
341  this.restartRequired = true;
342  } catch (ex) {
343  // Report exception.
344  Cu.reportError("Error installing add-on: " + ex);
345 
346  // Add-on install failed.
347  aInstallInfo.failed = true;
348  }
349 
350  // Remove the add-on file.
351  aInstallInfo.file.remove(false);
352  },
353 
354 
361  _presentErrors: function addOnBundleInstallerSvc__presentErrors() {
362  var errorCount = 0;
363 
364  // Fill the error listbox with the failed add-ons.
365  var errorListBoxElem = this._getElement("error_listbox");
366  for (var i = 0; i < this._addOnInstallList.length; i++) {
367  // Get add-on install info and skip if it did not fail to install.
368  var installInfo = this._addOnInstallList[i];
369  if (!installInfo.failed)
370  continue;
371 
372  // One more error.
373  errorCount++;
374 
375  // Get the add-on info.
376  var addOnBundleIndex = installInfo.index;
377  var addOnName = this._addOnBundle.getExtensionAttribute(addOnBundleIndex,
378  "name");
379  errorListBoxElem.appendItem(addOnName);
380  }
381 
382  // Present the error panel if any errors occurred.
383  if (errorCount > 0) {
384  // Set the error description line 1.
385  var description = SBFormattedCountString
386  ("add_on_bundle_installer.error.description1",
387  errorCount);
388  var descriptionTextNode = document.createTextNode(description);
389  var errorDescriptionElem = this._getElement("error_description_1");
390  errorDescriptionElem.appendChild(descriptionTextNode);
391 
392  // Set the error description line 2.
393  description = SBFormattedCountString
394  ("add_on_bundle_installer.error.description2",
395  errorCount,
396  [ SBStringBrandShortName() ]);
397  descriptionTextNode = document.createTextNode(description);
398  errorDescriptionElem = this._getElement("error_description_2");
399  errorDescriptionElem.appendChild(descriptionTextNode);
400 
401  // Show the error panel.
402  var statusDeckElem = this._getElement("status_deck");
403  var errorPanelElem = this._getElement("error_panel");
404  statusDeckElem.selectedPanel = errorPanelElem;
405  }
406 
407  // Return results.
408  return errorCount;
409  },
410 
411 
421  _getElement: function addOnBundleInstallerSvc__getElement(aElementID) {
422  return document.getAnonymousElementByAttribute(this._widget,
423  "anonid",
424  aElementID);
425  }
426 }
427 
const Cu
function Fx prototype initialize
const Cc
function SBFormattedString(aKey, aParams, aDefault, aStringBundle)
function onComplete(job)
Definition: test_bug7406.js:85
var event
function SBStringBrandShortName()
function SBFormattedCountString(aKeyBase, aCount, aParams, aDefault, aStringBundle)
DataRemote prototype constructor
return null
Definition: FeedWriter.js:1143
const Cr
const Ci
var failed
_getSelectedPageStyle s i
function addOnBundleInstallerSvc(aWidget)