|
1 // -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 "use strict"; |
|
8 |
|
9 Components.utils.import("resource://gre/modules/AddonManager.jsm"); |
|
10 Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); |
|
11 Components.utils.import("resource://gre/modules/Services.jsm"); |
|
12 |
|
13 const Cc = Components.classes; |
|
14 const Ci = Components.interfaces; |
|
15 |
|
16 var gView = null; |
|
17 |
|
18 function showView(aView) { |
|
19 gView = aView; |
|
20 |
|
21 gView.show(); |
|
22 |
|
23 // If the view's show method immediately showed a different view then don't |
|
24 // do anything else |
|
25 if (gView != aView) |
|
26 return; |
|
27 |
|
28 let viewNode = document.getElementById(gView.nodeID); |
|
29 viewNode.parentNode.selectedPanel = viewNode; |
|
30 |
|
31 // For testing dispatch an event when the view changes |
|
32 var event = document.createEvent("Events"); |
|
33 event.initEvent("ViewChanged", true, true); |
|
34 viewNode.dispatchEvent(event); |
|
35 } |
|
36 |
|
37 function showButtons(aCancel, aBack, aNext, aDone) { |
|
38 document.getElementById("cancel").hidden = !aCancel; |
|
39 document.getElementById("back").hidden = !aBack; |
|
40 document.getElementById("next").hidden = !aNext; |
|
41 document.getElementById("done").hidden = !aDone; |
|
42 } |
|
43 |
|
44 function isAddonDistroInstalled(aID) { |
|
45 let branch = Services.prefs.getBranch("extensions.installedDistroAddon."); |
|
46 if (!branch.prefHasUserValue(aID)) |
|
47 return false; |
|
48 |
|
49 return branch.getBoolPref(aID); |
|
50 } |
|
51 |
|
52 function orderForScope(aScope) { |
|
53 return aScope == AddonManager.SCOPE_PROFILE ? 1 : 0; |
|
54 } |
|
55 |
|
56 var gAddons = {}; |
|
57 |
|
58 var gChecking = { |
|
59 nodeID: "checking", |
|
60 |
|
61 _progress: null, |
|
62 _addonCount: 0, |
|
63 _completeCount: 0, |
|
64 |
|
65 show: function gChecking_show() { |
|
66 showButtons(true, false, false, false); |
|
67 this._progress = document.getElementById("checking-progress"); |
|
68 |
|
69 let self = this; |
|
70 AddonManager.getAllAddons(function gChecking_getAllAddons(aAddons) { |
|
71 if (aAddons.length == 0) { |
|
72 window.close(); |
|
73 return; |
|
74 } |
|
75 |
|
76 aAddons = aAddons.filter(function gChecking_filterAddons(aAddon) { |
|
77 if (aAddon.type == "plugin" || aAddon.type == "service") |
|
78 return false; |
|
79 |
|
80 if (aAddon.type == "theme") { |
|
81 // Don't show application shipped themes |
|
82 if (aAddon.scope == AddonManager.SCOPE_APPLICATION) |
|
83 return false; |
|
84 // Don't show already disabled themes |
|
85 if (aAddon.userDisabled) |
|
86 return false; |
|
87 } |
|
88 |
|
89 return true; |
|
90 }); |
|
91 |
|
92 self._addonCount = aAddons.length; |
|
93 self._progress.value = 0; |
|
94 self._progress.max = aAddons.length; |
|
95 self._progress.mode = "determined"; |
|
96 |
|
97 // Ensure compatibility overrides are up to date before checking for |
|
98 // individual addon updates. |
|
99 let ids = [addon.id for each (addon in aAddons)]; |
|
100 AddonRepository.repopulateCache(ids, function gChecking_repopulateCache() { |
|
101 for (let addonItem of aAddons) { |
|
102 // Ignore disabled themes |
|
103 if (addonItem.type != "theme" || !addonItem.userDisabled) { |
|
104 gAddons[addonItem.id] = { |
|
105 addon: addonItem, |
|
106 install: null, |
|
107 wasActive: addonItem.isActive |
|
108 } |
|
109 } |
|
110 |
|
111 addonItem.findUpdates(self, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); |
|
112 } |
|
113 }); |
|
114 }); |
|
115 }, |
|
116 |
|
117 onUpdateAvailable: function gChecking_onUpdateAvailable(aAddon, aInstall) { |
|
118 // If the add-on can be upgraded then remember the new version |
|
119 if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE) |
|
120 gAddons[aAddon.id].install = aInstall; |
|
121 }, |
|
122 |
|
123 onUpdateFinished: function gChecking_onUpdateFinished(aAddon, aError) { |
|
124 this._completeCount++; |
|
125 this._progress.value = this._completeCount; |
|
126 |
|
127 if (this._completeCount < this._addonCount) |
|
128 return; |
|
129 |
|
130 var addons = [gAddons[id] for (id in gAddons)]; |
|
131 |
|
132 addons.sort(function sortAddons(a, b) { |
|
133 let orderA = orderForScope(a.addon.scope); |
|
134 let orderB = orderForScope(b.addon.scope); |
|
135 |
|
136 if (orderA != orderB) |
|
137 return orderA - orderB; |
|
138 |
|
139 return String.localeCompare(a.addon.name, b.addon.name); |
|
140 }); |
|
141 |
|
142 let rows = document.getElementById("select-rows"); |
|
143 let lastAddon = null; |
|
144 for (let entry of addons) { |
|
145 if (lastAddon && |
|
146 orderForScope(entry.addon.scope) != orderForScope(lastAddon.scope)) { |
|
147 let separator = document.createElement("separator"); |
|
148 rows.appendChild(separator); |
|
149 } |
|
150 |
|
151 let row = document.createElement("row"); |
|
152 row.setAttribute("id", entry.addon.id); |
|
153 row.setAttribute("class", "addon"); |
|
154 rows.appendChild(row); |
|
155 row.setAddon(entry.addon, entry.install, entry.wasActive, |
|
156 isAddonDistroInstalled(entry.addon.id)); |
|
157 |
|
158 if (entry.install) |
|
159 entry.install.addListener(gUpdate); |
|
160 |
|
161 lastAddon = entry.addon; |
|
162 } |
|
163 |
|
164 showView(gSelect); |
|
165 } |
|
166 }; |
|
167 |
|
168 var gSelect = { |
|
169 nodeID: "select", |
|
170 |
|
171 show: function gSelect_show() { |
|
172 this.updateButtons(); |
|
173 }, |
|
174 |
|
175 updateButtons: function gSelect_updateButtons() { |
|
176 for (let row = document.getElementById("select-rows").firstChild; |
|
177 row; row = row.nextSibling) { |
|
178 if (row.localName == "separator") |
|
179 continue; |
|
180 |
|
181 if (row.action) { |
|
182 showButtons(false, false, true, false); |
|
183 return; |
|
184 } |
|
185 } |
|
186 |
|
187 showButtons(false, false, false, true); |
|
188 }, |
|
189 |
|
190 next: function gSelect_next() { |
|
191 showView(gConfirm); |
|
192 }, |
|
193 |
|
194 done: function gSelect_done() { |
|
195 window.close(); |
|
196 } |
|
197 }; |
|
198 |
|
199 var gConfirm = { |
|
200 nodeID: "confirm", |
|
201 |
|
202 show: function gConfirm_show() { |
|
203 showButtons(false, true, false, true); |
|
204 |
|
205 let box = document.getElementById("confirm-scrollbox").firstChild; |
|
206 while (box) { |
|
207 box.hidden = true; |
|
208 while (box.lastChild != box.firstChild) |
|
209 box.removeChild(box.lastChild); |
|
210 box = box.nextSibling; |
|
211 } |
|
212 |
|
213 for (let row = document.getElementById("select-rows").firstChild; |
|
214 row; row = row.nextSibling) { |
|
215 if (row.localName == "separator") |
|
216 continue; |
|
217 |
|
218 let action = row.action; |
|
219 if (!action) |
|
220 continue; |
|
221 |
|
222 let list = document.getElementById(action + "-list"); |
|
223 |
|
224 list.hidden = false; |
|
225 let item = document.createElement("hbox"); |
|
226 item.setAttribute("id", row._addon.id); |
|
227 item.setAttribute("class", "addon"); |
|
228 item.setAttribute("type", row._addon.type); |
|
229 item.setAttribute("name", row._addon.name); |
|
230 if (action == "update" || action == "enable") |
|
231 item.setAttribute("active", "true"); |
|
232 list.appendChild(item); |
|
233 |
|
234 if (action == "update") |
|
235 showButtons(false, true, true, false); |
|
236 } |
|
237 }, |
|
238 |
|
239 back: function gConfirm_back() { |
|
240 showView(gSelect); |
|
241 }, |
|
242 |
|
243 next: function gConfirm_next() { |
|
244 showView(gUpdate); |
|
245 }, |
|
246 |
|
247 done: function gConfirm_done() { |
|
248 for (let row = document.getElementById("select-rows").firstChild; |
|
249 row; row = row.nextSibling) { |
|
250 if (row.localName != "separator") |
|
251 row.apply(); |
|
252 } |
|
253 |
|
254 window.close(); |
|
255 } |
|
256 } |
|
257 |
|
258 var gUpdate = { |
|
259 nodeID: "update", |
|
260 |
|
261 _progress: null, |
|
262 _waitingCount: 0, |
|
263 _completeCount: 0, |
|
264 _errorCount: 0, |
|
265 |
|
266 show: function gUpdate_show() { |
|
267 showButtons(true, false, false, false); |
|
268 |
|
269 this._progress = document.getElementById("update-progress"); |
|
270 |
|
271 for (let row = document.getElementById("select-rows").firstChild; |
|
272 row; row = row.nextSibling) { |
|
273 if (row.localName != "separator") |
|
274 row.apply(); |
|
275 } |
|
276 |
|
277 this._progress.mode = "determined"; |
|
278 this._progress.max = this._waitingCount; |
|
279 this._progress.value = this._completeCount; |
|
280 }, |
|
281 |
|
282 checkComplete: function gUpdate_checkComplete() { |
|
283 this._progress.value = this._completeCount; |
|
284 if (this._completeCount < this._waitingCount) |
|
285 return; |
|
286 |
|
287 if (this._errorCount > 0) { |
|
288 showView(gErrors); |
|
289 return; |
|
290 } |
|
291 |
|
292 window.close(); |
|
293 }, |
|
294 |
|
295 onDownloadStarted: function gUpdate_onDownloadStarted(aInstall) { |
|
296 this._waitingCount++; |
|
297 }, |
|
298 |
|
299 onDownloadFailed: function gUpdate_onDownloadFailed(aInstall) { |
|
300 this._errorCount++; |
|
301 this._completeCount++; |
|
302 this.checkComplete(); |
|
303 }, |
|
304 |
|
305 onInstallFailed: function gUpdate_onInstallFailed(aInstall) { |
|
306 this._errorCount++; |
|
307 this._completeCount++; |
|
308 this.checkComplete(); |
|
309 }, |
|
310 |
|
311 onInstallEnded: function gUpdate_onInstallEnded(aInstall) { |
|
312 this._completeCount++; |
|
313 this.checkComplete(); |
|
314 } |
|
315 }; |
|
316 |
|
317 var gErrors = { |
|
318 nodeID: "errors", |
|
319 |
|
320 show: function gErrors_show() { |
|
321 showButtons(false, false, false, true); |
|
322 }, |
|
323 |
|
324 done: function gErrors_done() { |
|
325 window.close(); |
|
326 } |
|
327 }; |
|
328 |
|
329 window.addEventListener("load", function loadEventListener() { |
|
330 showView(gChecking); }, false); |
|
331 |
|
332 // When closing the window cancel any pending or in-progress installs |
|
333 window.addEventListener("unload", function unloadEventListener() { |
|
334 for (let id in gAddons) { |
|
335 let entry = gAddons[id]; |
|
336 if (!entry.install) |
|
337 return; |
|
338 |
|
339 aEntry.install.removeListener(gUpdate); |
|
340 |
|
341 if (entry.install.state != AddonManager.STATE_INSTALLED && |
|
342 entry.install.state != AddonManager.STATE_DOWNLOAD_FAILED && |
|
343 entry.install.state != AddonManager.STATE_INSTALL_FAILED) { |
|
344 entry.install.cancel(); |
|
345 } |
|
346 } |
|
347 }, false); |