|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ |
|
3 */ |
|
4 |
|
5 // This verifies that updating an add-on to a new ID works |
|
6 |
|
7 // The test extension uses an insecure update url. |
|
8 Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); |
|
9 |
|
10 Components.utils.import("resource://testing-common/httpd.js"); |
|
11 var testserver; |
|
12 const profileDir = gProfD.clone(); |
|
13 profileDir.append("extensions"); |
|
14 |
|
15 function resetPrefs() { |
|
16 Services.prefs.setIntPref("bootstraptest.active_version", -1); |
|
17 Services.prefs.setIntPref("bootstraptest.installed_version", -1); |
|
18 Services.prefs.setIntPref("bootstraptest.startup_reason", -1); |
|
19 Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1); |
|
20 Services.prefs.setIntPref("bootstraptest.install_reason", -1); |
|
21 Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1); |
|
22 } |
|
23 |
|
24 function getActiveVersion() { |
|
25 return Services.prefs.getIntPref("bootstraptest.active_version"); |
|
26 } |
|
27 |
|
28 function getInstalledVersion() { |
|
29 return Services.prefs.getIntPref("bootstraptest.installed_version"); |
|
30 } |
|
31 |
|
32 function run_test() { |
|
33 createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); |
|
34 |
|
35 // Create and configure the HTTP server. |
|
36 testserver = new HttpServer(); |
|
37 testserver.registerDirectory("/data/", do_get_file("data")); |
|
38 testserver.registerDirectory("/addons/", do_get_file("addons")); |
|
39 testserver.start(4444); |
|
40 |
|
41 do_test_pending(); |
|
42 run_test_1(); |
|
43 } |
|
44 |
|
45 function end_test() { |
|
46 testserver.stop(do_test_finished); |
|
47 } |
|
48 |
|
49 function installUpdate(aInstall, aCallback) { |
|
50 aInstall.addListener({ |
|
51 onInstallEnded: function(aInstall) { |
|
52 // give the startup time to run |
|
53 do_execute_soon(function() { |
|
54 aCallback(aInstall); |
|
55 }); |
|
56 } |
|
57 }); |
|
58 |
|
59 aInstall.install(); |
|
60 } |
|
61 |
|
62 // Verify that an update to an add-on with a new ID uninstalls the old add-on |
|
63 function run_test_1() { |
|
64 writeInstallRDFForExtension({ |
|
65 id: "addon1@tests.mozilla.org", |
|
66 version: "1.0", |
|
67 updateURL: "http://localhost:4444/data/test_updateid.rdf", |
|
68 targetApplications: [{ |
|
69 id: "xpcshell@tests.mozilla.org", |
|
70 minVersion: "1", |
|
71 maxVersion: "1" |
|
72 }], |
|
73 name: "Test Addon 1", |
|
74 }, profileDir); |
|
75 |
|
76 startupManager(); |
|
77 |
|
78 AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { |
|
79 do_check_neq(a1, null); |
|
80 do_check_eq(a1.version, "1.0"); |
|
81 |
|
82 a1.findUpdates({ |
|
83 onUpdateAvailable: function(addon, install) { |
|
84 do_check_eq(install.name, addon.name); |
|
85 do_check_eq(install.version, "2.0"); |
|
86 do_check_eq(install.state, AddonManager.STATE_AVAILABLE); |
|
87 do_check_eq(install.existingAddon, a1); |
|
88 |
|
89 installUpdate(install, check_test_1); |
|
90 } |
|
91 }, AddonManager.UPDATE_WHEN_USER_REQUESTED); |
|
92 }); |
|
93 } |
|
94 |
|
95 function check_test_1(install) { |
|
96 AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { |
|
97 // Existing add-on should have a pending upgrade |
|
98 do_check_neq(a1.pendingUpgrade, null); |
|
99 do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org"); |
|
100 do_check_eq(a1.pendingUpgrade.install.existingAddon, a1); |
|
101 do_check_neq(a1.syncGUID); |
|
102 |
|
103 let a1SyncGUID = a1.syncGUID; |
|
104 |
|
105 restartManager(); |
|
106 |
|
107 AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", |
|
108 "addon2@tests.mozilla.org"], function([a1, a2]) { |
|
109 // Should have uninstalled the old and installed the new |
|
110 do_check_eq(a1, null); |
|
111 do_check_neq(a2, null); |
|
112 do_check_neq(a2.syncGUID, null); |
|
113 |
|
114 // The Sync GUID should change when the ID changes |
|
115 do_check_neq(a1SyncGUID, a2.syncGUID); |
|
116 |
|
117 a2.uninstall(); |
|
118 |
|
119 do_execute_soon(run_test_2); |
|
120 }); |
|
121 })); |
|
122 } |
|
123 |
|
124 // Test that when the new add-on already exists we just upgrade that |
|
125 function run_test_2() { |
|
126 restartManager(); |
|
127 shutdownManager(); |
|
128 |
|
129 writeInstallRDFForExtension({ |
|
130 id: "addon1@tests.mozilla.org", |
|
131 version: "1.0", |
|
132 updateURL: "http://localhost:4444/data/test_updateid.rdf", |
|
133 targetApplications: [{ |
|
134 id: "xpcshell@tests.mozilla.org", |
|
135 minVersion: "1", |
|
136 maxVersion: "1" |
|
137 }], |
|
138 name: "Test Addon 1", |
|
139 }, profileDir); |
|
140 writeInstallRDFForExtension({ |
|
141 id: "addon2@tests.mozilla.org", |
|
142 version: "1.0", |
|
143 targetApplications: [{ |
|
144 id: "xpcshell@tests.mozilla.org", |
|
145 minVersion: "1", |
|
146 maxVersion: "1" |
|
147 }], |
|
148 name: "Test Addon 2", |
|
149 }, profileDir); |
|
150 |
|
151 startupManager(); |
|
152 |
|
153 AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { |
|
154 do_check_neq(a1, null); |
|
155 do_check_eq(a1.version, "1.0"); |
|
156 |
|
157 a1.findUpdates({ |
|
158 onUpdateAvailable: function(addon, install) { |
|
159 installUpdate(install, check_test_2); |
|
160 } |
|
161 }, AddonManager.UPDATE_WHEN_USER_REQUESTED); |
|
162 }); |
|
163 } |
|
164 |
|
165 function check_test_2(install) { |
|
166 AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", |
|
167 "addon2@tests.mozilla.org"], |
|
168 callback_soon(function([a1, a2]) { |
|
169 do_check_eq(a1.pendingUpgrade, null); |
|
170 // Existing add-on should have a pending upgrade |
|
171 do_check_neq(a2.pendingUpgrade, null); |
|
172 do_check_eq(a2.pendingUpgrade.id, "addon2@tests.mozilla.org"); |
|
173 do_check_eq(a2.pendingUpgrade.install.existingAddon, a2); |
|
174 |
|
175 restartManager(); |
|
176 |
|
177 AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", |
|
178 "addon2@tests.mozilla.org"], function([a1, a2]) { |
|
179 // Should have uninstalled the old and installed the new |
|
180 do_check_neq(a1, null); |
|
181 do_check_neq(a2, null); |
|
182 |
|
183 a1.uninstall(); |
|
184 a2.uninstall(); |
|
185 |
|
186 do_execute_soon(run_test_3); |
|
187 }); |
|
188 })); |
|
189 } |
|
190 |
|
191 // Test that we rollback correctly when removing the old add-on fails |
|
192 function run_test_3() { |
|
193 restartManager(); |
|
194 shutdownManager(); |
|
195 |
|
196 // This test only works on Windows |
|
197 if (!("nsIWindowsRegKey" in AM_Ci)) { |
|
198 run_test_4(); |
|
199 return; |
|
200 } |
|
201 |
|
202 writeInstallRDFForExtension({ |
|
203 id: "addon1@tests.mozilla.org", |
|
204 version: "1.0", |
|
205 updateURL: "http://localhost:4444/data/test_updateid.rdf", |
|
206 targetApplications: [{ |
|
207 id: "xpcshell@tests.mozilla.org", |
|
208 minVersion: "1", |
|
209 maxVersion: "1" |
|
210 }], |
|
211 name: "Test Addon 1", |
|
212 }, profileDir); |
|
213 |
|
214 startupManager(); |
|
215 |
|
216 AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { |
|
217 do_check_neq(a1, null); |
|
218 do_check_eq(a1.version, "1.0"); |
|
219 |
|
220 a1.findUpdates({ |
|
221 onUpdateAvailable: function(addon, install) { |
|
222 installUpdate(install, check_test_3); |
|
223 } |
|
224 }, AddonManager.UPDATE_WHEN_USER_REQUESTED); |
|
225 }); |
|
226 } |
|
227 |
|
228 function check_test_3(install) { |
|
229 AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { |
|
230 // Existing add-on should have a pending upgrade |
|
231 do_check_neq(a1.pendingUpgrade, null); |
|
232 do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org"); |
|
233 do_check_eq(a1.pendingUpgrade.install.existingAddon, a1); |
|
234 |
|
235 // Lock the old add-on open so it can't be uninstalled |
|
236 var file = profileDir.clone(); |
|
237 file.append("addon1@tests.mozilla.org"); |
|
238 if (!file.exists()) |
|
239 file.leafName += ".xpi"; |
|
240 else |
|
241 file.append("install.rdf"); |
|
242 |
|
243 var fstream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. |
|
244 createInstance(AM_Ci.nsIFileOutputStream); |
|
245 fstream.init(file, FileUtils.MODE_APPEND | FileUtils.MODE_WRONLY, FileUtils.PERMS_FILE, 0); |
|
246 |
|
247 restartManager(); |
|
248 |
|
249 fstream.close(); |
|
250 |
|
251 AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", |
|
252 "addon2@tests.mozilla.org"], |
|
253 callback_soon(function([a1, a2]) { |
|
254 // Should not have installed the new add-on but it should still be |
|
255 // pending install |
|
256 do_check_neq(a1, null); |
|
257 do_check_eq(a2, null); |
|
258 |
|
259 restartManager(); |
|
260 |
|
261 AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", |
|
262 "addon2@tests.mozilla.org"], function([a1, a2]) { |
|
263 // Should have installed the new add-on |
|
264 do_check_eq(a1, null); |
|
265 do_check_neq(a2, null); |
|
266 |
|
267 a2.uninstall(); |
|
268 |
|
269 do_execute_soon(run_test_4); |
|
270 }); |
|
271 })); |
|
272 })); |
|
273 } |
|
274 |
|
275 // Tests that upgrading to a bootstrapped add-on works but requires a restart |
|
276 function run_test_4() { |
|
277 restartManager(); |
|
278 shutdownManager(); |
|
279 |
|
280 writeInstallRDFForExtension({ |
|
281 id: "addon2@tests.mozilla.org", |
|
282 version: "2.0", |
|
283 updateURL: "http://localhost:4444/data/test_updateid.rdf", |
|
284 targetApplications: [{ |
|
285 id: "xpcshell@tests.mozilla.org", |
|
286 minVersion: "1", |
|
287 maxVersion: "1" |
|
288 }], |
|
289 name: "Test Addon 2", |
|
290 }, profileDir); |
|
291 |
|
292 startupManager(); |
|
293 |
|
294 resetPrefs(); |
|
295 |
|
296 AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { |
|
297 do_check_neq(a2, null); |
|
298 do_check_neq(a2.syncGUID, null); |
|
299 do_check_eq(a2.version, "2.0"); |
|
300 |
|
301 a2.findUpdates({ |
|
302 onUpdateAvailable: function(addon, install) { |
|
303 installUpdate(install, check_test_4); |
|
304 } |
|
305 }, AddonManager.UPDATE_WHEN_USER_REQUESTED); |
|
306 }); |
|
307 } |
|
308 |
|
309 function check_test_4() { |
|
310 AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", |
|
311 "addon3@tests.mozilla.org"], |
|
312 callback_soon(function([a2, a3]) { |
|
313 // Should still be pending install even though the new add-on is restartless |
|
314 do_check_neq(a2, null); |
|
315 do_check_eq(a3, null); |
|
316 |
|
317 do_check_neq(a2.pendingUpgrade, null); |
|
318 do_check_eq(a2.pendingUpgrade.id, "addon3@tests.mozilla.org"); |
|
319 |
|
320 do_check_eq(getInstalledVersion(), -1); |
|
321 do_check_eq(getActiveVersion(), -1); |
|
322 |
|
323 restartManager(); |
|
324 |
|
325 AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", |
|
326 "addon3@tests.mozilla.org"], function([a2, a3]) { |
|
327 // Should have updated |
|
328 do_check_eq(a2, null); |
|
329 do_check_neq(a3, null); |
|
330 |
|
331 do_check_eq(getInstalledVersion(), 3); |
|
332 do_check_eq(getActiveVersion(), 3); |
|
333 |
|
334 do_execute_soon(run_test_5); |
|
335 }); |
|
336 })); |
|
337 } |
|
338 |
|
339 // Tests that upgrading to another bootstrapped add-on works without a restart |
|
340 function run_test_5() { |
|
341 AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { |
|
342 do_check_neq(a3, null); |
|
343 do_check_eq(a3.version, "3.0"); |
|
344 |
|
345 a3.findUpdates({ |
|
346 onUpdateAvailable: function(addon, install) { |
|
347 installUpdate(install, check_test_5); |
|
348 } |
|
349 }, AddonManager.UPDATE_WHEN_USER_REQUESTED); |
|
350 }); |
|
351 } |
|
352 |
|
353 function check_test_5() { |
|
354 AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org", |
|
355 "addon4@tests.mozilla.org"], |
|
356 callback_soon(function([a3, a4]) { |
|
357 // Should have updated |
|
358 do_check_eq(a3, null); |
|
359 do_check_neq(a4, null); |
|
360 |
|
361 do_check_eq(getInstalledVersion(), 4); |
|
362 do_check_eq(getActiveVersion(), 4); |
|
363 |
|
364 restartManager(); |
|
365 |
|
366 AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org", |
|
367 "addon4@tests.mozilla.org"], function([a3, a4]) { |
|
368 // Should still be gone |
|
369 do_check_eq(a3, null); |
|
370 do_check_neq(a4, null); |
|
371 |
|
372 do_check_eq(getInstalledVersion(), 4); |
|
373 do_check_eq(getActiveVersion(), 4); |
|
374 |
|
375 run_test_6(); |
|
376 }); |
|
377 })); |
|
378 } |
|
379 |
|
380 // Tests that upgrading to a non-bootstrapped add-on works but requires a restart |
|
381 function run_test_6() { |
|
382 AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { |
|
383 do_check_neq(a4, null); |
|
384 do_check_eq(a4.version, "4.0"); |
|
385 |
|
386 a4.findUpdates({ |
|
387 onUpdateAvailable: function(addon, install) { |
|
388 installUpdate(install, check_test_6); |
|
389 } |
|
390 }, AddonManager.UPDATE_WHEN_USER_REQUESTED); |
|
391 }); |
|
392 } |
|
393 |
|
394 function check_test_6() { |
|
395 AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", |
|
396 "addon2@tests.mozilla.org"], |
|
397 callback_soon(function([a4, a2]) { |
|
398 // Should still be pending install even though the old add-on is restartless |
|
399 do_check_neq(a4, null); |
|
400 do_check_eq(a2, null); |
|
401 |
|
402 do_check_neq(a4.pendingUpgrade, null); |
|
403 do_check_eq(a4.pendingUpgrade.id, "addon2@tests.mozilla.org"); |
|
404 |
|
405 do_check_eq(getInstalledVersion(), 4); |
|
406 do_check_eq(getActiveVersion(), 4); |
|
407 |
|
408 restartManager(); |
|
409 |
|
410 AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", |
|
411 "addon2@tests.mozilla.org"], function([a4, a2]) { |
|
412 // Should have updated |
|
413 do_check_eq(a4, null); |
|
414 do_check_neq(a2, null); |
|
415 |
|
416 do_check_eq(getInstalledVersion(), 0); |
|
417 do_check_eq(getActiveVersion(), 0); |
|
418 |
|
419 end_test(); |
|
420 }); |
|
421 })); |
|
422 } |