Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 */
6 const Cc = Components.classes;
7 const Ci = Components.interfaces;
8 const Cu = Components.utils;
9 const Cr = Components.results;
11 const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
13 Cu.import("resource://testing-common/httpd.js");
14 var gTestserver = new HttpServer();
15 gTestserver.start(-1);
16 gPort = gTestserver.identity.primaryPort;
18 // register static files with server and interpolate port numbers in them
19 mapFile("/data/bug455906_warn.xml", gTestserver);
20 mapFile("/data/bug455906_start.xml", gTestserver);
21 mapFile("/data/bug455906_block.xml", gTestserver);
22 mapFile("/data/bug455906_empty.xml", gTestserver);
24 // Workaround for Bug 658720 - URL formatter can leak during xpcshell tests
25 const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL";
26 Services.prefs.setCharPref(PREF_BLOCKLIST_ITEM_URL, "http://localhost:" + gPort + "/blocklist/%blockID%");
28 var ADDONS = [{
29 // Tests how the blocklist affects a disabled add-on
30 id: "test_bug455906_1@tests.mozilla.org",
31 name: "Bug 455906 Addon Test 1",
32 version: "5",
33 appVersion: "3"
34 }, {
35 // Tests how the blocklist affects an enabled add-on
36 id: "test_bug455906_2@tests.mozilla.org",
37 name: "Bug 455906 Addon Test 2",
38 version: "5",
39 appVersion: "3"
40 }, {
41 // Tests how the blocklist affects an enabled add-on, to be disabled by the notification
42 id: "test_bug455906_3@tests.mozilla.org",
43 name: "Bug 455906 Addon Test 3",
44 version: "5",
45 appVersion: "3"
46 }, {
47 // Tests how the blocklist affects a disabled add-on that was already warned about
48 id: "test_bug455906_4@tests.mozilla.org",
49 name: "Bug 455906 Addon Test 4",
50 version: "5",
51 appVersion: "3"
52 }, {
53 // Tests how the blocklist affects an enabled add-on that was already warned about
54 id: "test_bug455906_5@tests.mozilla.org",
55 name: "Bug 455906 Addon Test 5",
56 version: "5",
57 appVersion: "3"
58 }, {
59 // Tests how the blocklist affects an already blocked add-on
60 id: "test_bug455906_6@tests.mozilla.org",
61 name: "Bug 455906 Addon Test 6",
62 version: "5",
63 appVersion: "3"
64 }, {
65 // Tests how the blocklist affects an incompatible add-on
66 id: "test_bug455906_7@tests.mozilla.org",
67 name: "Bug 455906 Addon Test 7",
68 version: "5",
69 appVersion: "2"
70 }, {
71 // Spare add-on used to ensure we get a notification when switching lists
72 id: "dummy_bug455906_1@tests.mozilla.org",
73 name: "Dummy Addon 1",
74 version: "5",
75 appVersion: "3"
76 }, {
77 // Spare add-on used to ensure we get a notification when switching lists
78 id: "dummy_bug455906_2@tests.mozilla.org",
79 name: "Dummy Addon 2",
80 version: "5",
81 appVersion: "3"
82 }];
84 function MockPlugin(name, version, enabledState) {
85 this.name = name;
86 this.version = version;
87 this.enabledState = enabledState;
88 }
89 Object.defineProperty(MockPlugin.prototype, "blocklisted", {
90 get: function MockPlugin_getBlocklisted() {
91 let bls = Cc["@mozilla.org/extensions/blocklist;1"].getService(Ci.nsIBlocklistService);
92 return bls.getPluginBlocklistState(this) == bls.STATE_BLOCKED;
93 }
94 });
95 Object.defineProperty(MockPlugin.prototype, "disabled", {
96 get: function MockPlugin_getDisabled() {
97 return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED;
98 }
99 });
101 var PLUGINS = [
102 // Tests how the blocklist affects a disabled plugin
103 new MockPlugin("test_bug455906_1", "5", Ci.nsIPluginTag.STATE_DISABLED),
104 // Tests how the blocklist affects an enabled plugin
105 new MockPlugin("test_bug455906_2", "5", Ci.nsIPluginTag.STATE_ENABLED),
106 // Tests how the blocklist affects an enabled plugin, to be disabled by the notification
107 new MockPlugin("test_bug455906_3", "5", Ci.nsIPluginTag.STATE_ENABLED),
108 // Tests how the blocklist affects a disabled plugin that was already warned about
109 new MockPlugin("test_bug455906_4", "5", Ci.nsIPluginTag.STATE_DISABLED),
110 // Tests how the blocklist affects an enabled plugin that was already warned about
111 new MockPlugin("test_bug455906_5", "5", Ci.nsIPluginTag.STATE_ENABLED),
112 // Tests how the blocklist affects an already blocked plugin
113 new MockPlugin("test_bug455906_6", "5", Ci.nsIPluginTag.STATE_ENABLED)
114 ];
116 var gNotificationCheck = null;
117 var gTestCheck = null;
119 // A fake plugin host for the blocklist service to use
120 var PluginHost = {
121 getPluginTags: function(countRef) {
122 countRef.value = PLUGINS.length;
123 return PLUGINS;
124 },
126 QueryInterface: function(iid) {
127 if (iid.equals(Ci.nsIPluginHost)
128 || iid.equals(Ci.nsISupports))
129 return this;
131 throw Components.results.NS_ERROR_NO_INTERFACE;
132 }
133 }
135 var PluginHostFactory = {
136 createInstance: function (outer, iid) {
137 if (outer != null)
138 throw Components.results.NS_ERROR_NO_AGGREGATION;
139 return PluginHost.QueryInterface(iid);
140 }
141 };
143 // Don't need the full interface, attempts to call other methods will just
144 // throw which is just fine
145 var WindowWatcher = {
146 openWindow: function(parent, url, name, features, windowArguments) {
147 // Should be called to list the newly blocklisted items
148 do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG);
150 if (gNotificationCheck) {
151 var args = windowArguments.wrappedJSObject;
152 gNotificationCheck(args);
153 }
155 //run the code after the blocklist is closed
156 Services.obs.notifyObservers(null, "addon-blocklist-closed", null);
158 // Call the next test after the blocklist has finished up
159 do_timeout(0, gTestCheck);
160 },
162 QueryInterface: function(iid) {
163 if (iid.equals(Ci.nsIWindowWatcher)
164 || iid.equals(Ci.nsISupports))
165 return this;
167 throw Cr.NS_ERROR_NO_INTERFACE;
168 }
169 }
171 var WindowWatcherFactory = {
172 createInstance: function createInstance(outer, iid) {
173 if (outer != null)
174 throw Components.results.NS_ERROR_NO_AGGREGATION;
175 return WindowWatcher.QueryInterface(iid);
176 }
177 };
178 var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
179 registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"),
180 "Fake Plugin Host",
181 "@mozilla.org/plugin/host;1", PluginHostFactory);
182 registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"),
183 "Fake Window Watcher",
184 "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory);
186 function create_addon(addon) {
187 var installrdf = "<?xml version=\"1.0\"?>\n" +
188 "\n" +
189 "<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" +
190 " xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" +
191 " <Description about=\"urn:mozilla:install-manifest\">\n" +
192 " <em:id>" + addon.id + "</em:id>\n" +
193 " <em:version>" + addon.version + "</em:version>\n" +
194 " <em:targetApplication>\n" +
195 " <Description>\n" +
196 " <em:id>xpcshell@tests.mozilla.org</em:id>\n" +
197 " <em:minVersion>" + addon.appVersion + "</em:minVersion>\n" +
198 " <em:maxVersion>" + addon.appVersion + "</em:maxVersion>\n" +
199 " </Description>\n" +
200 " </em:targetApplication>\n" +
201 " <em:name>" + addon.name + "</em:name>\n" +
202 " </Description>\n" +
203 "</RDF>\n";
204 var target = gProfD.clone();
205 target.append("extensions");
206 target.append(addon.id);
207 target.append("install.rdf");
208 target.create(target.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
209 var stream = Cc["@mozilla.org/network/file-output-stream;1"].
210 createInstance(Ci.nsIFileOutputStream);
211 stream.init(target,
212 FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE,
213 FileUtils.PERMS_FILE, 0);
214 stream.write(installrdf, installrdf.length);
215 stream.close();
216 }
218 function load_blocklist(file) {
219 Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/" + file);
220 var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
221 getService(Ci.nsITimerCallback);
222 blocklist.notify(null);
223 }
225 function check_addon_state(addon) {
226 return addon.userDisabled + "," + addon.softDisabled + "," + addon.appDisabled;
227 }
229 function check_plugin_state(plugin) {
230 return plugin.disabled + "," + plugin.blocklisted;
231 }
233 function create_blocklistURL(blockID){
234 let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL);
235 url = url.replace(/%blockID%/g, blockID);
236 return url;
237 }
239 // Performs the initial setup
240 function run_test() {
241 // Setup for test
242 dump("Setting up tests\n");
243 // Rather than keeping lots of identical add-ons in version control, just
244 // write them into the profile.
245 for (let addon of ADDONS)
246 create_addon(addon);
248 // Copy the initial blocklist into the profile to check add-ons start in the
249 // right state.
250 copyBlocklistToProfile(do_get_file("data/bug455906_start.xml"));
252 createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8");
253 startupManager();
255 do_test_pending();
256 check_test_pt1();
257 }
259 // Before every main test this is the state the add-ons are meant to be in
260 function check_initial_state(callback) {
261 AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) {
262 do_check_eq(check_addon_state(addons[0]), "true,false,false");
263 do_check_eq(check_addon_state(addons[1]), "false,false,false");
264 do_check_eq(check_addon_state(addons[2]), "false,false,false");
265 do_check_eq(check_addon_state(addons[3]), "true,true,false");
266 do_check_eq(check_addon_state(addons[4]), "false,false,false");
267 do_check_eq(check_addon_state(addons[5]), "false,false,true");
268 do_check_eq(check_addon_state(addons[6]), "false,false,true");
270 do_check_eq(check_plugin_state(PLUGINS[0]), "true,false");
271 do_check_eq(check_plugin_state(PLUGINS[1]), "false,false");
272 do_check_eq(check_plugin_state(PLUGINS[2]), "false,false");
273 do_check_eq(check_plugin_state(PLUGINS[3]), "true,false");
274 do_check_eq(check_plugin_state(PLUGINS[4]), "false,false");
275 do_check_eq(check_plugin_state(PLUGINS[5]), "false,true");
277 callback();
278 });
279 }
281 // Tests the add-ons were installed and the initial blocklist applied as expected
282 function check_test_pt1() {
283 dump("Checking pt 1\n");
285 AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) {
286 for (var i = 0; i < ADDONS.length; i++) {
287 if (!addons[i])
288 do_throw("Addon " + (i + 1) + " did not get installed correctly");
289 }
291 do_check_eq(check_addon_state(addons[0]), "false,false,false");
292 do_check_eq(check_addon_state(addons[1]), "false,false,false");
293 do_check_eq(check_addon_state(addons[2]), "false,false,false");
295 // Warn add-ons should be soft disabled automatically
296 do_check_eq(check_addon_state(addons[3]), "true,true,false");
297 do_check_eq(check_addon_state(addons[4]), "true,true,false");
299 // Blocked and incompatible should be app disabled only
300 do_check_eq(check_addon_state(addons[5]), "false,false,true");
301 do_check_eq(check_addon_state(addons[6]), "false,false,true");
303 // We've overridden the plugin host so we cannot tell what that would have
304 // initialised the plugins as
306 // Put the add-ons into the base state
307 addons[0].userDisabled = true;
308 addons[4].userDisabled = false;
310 restartManager();
311 check_initial_state(function() {
312 gNotificationCheck = check_notification_pt2;
313 gTestCheck = check_test_pt2;
314 load_blocklist("bug455906_warn.xml");
315 });
316 }));
317 }
319 function check_notification_pt2(args) {
320 dump("Checking notification pt 2\n");
321 do_check_eq(args.list.length, 4);
323 for (let addon of args.list) {
324 if (addon.item instanceof Ci.nsIPluginTag) {
325 switch (addon.item.name) {
326 case "test_bug455906_2":
327 do_check_false(addon.blocked);
328 break;
329 case "test_bug455906_3":
330 do_check_false(addon.blocked);
331 addon.disable = true;
332 break;
333 default:
334 do_throw("Unknown addon: " + addon.item.name);
335 }
336 }
337 else {
338 switch (addon.item.id) {
339 case "test_bug455906_2@tests.mozilla.org":
340 do_check_false(addon.blocked);
341 break;
342 case "test_bug455906_3@tests.mozilla.org":
343 do_check_false(addon.blocked);
344 addon.disable = true;
345 break;
346 default:
347 do_throw("Unknown addon: " + addon.item.id);
348 }
349 }
350 }
351 }
353 function check_test_pt2() {
354 restartManager();
355 dump("Checking results pt 2\n");
357 AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) {
358 // Should have disabled this add-on as requested
359 do_check_eq(check_addon_state(addons[2]), "true,true,false");
360 do_check_eq(check_plugin_state(PLUGINS[2]), "true,false");
362 // The blocked add-on should have changed to soft disabled
363 do_check_eq(check_addon_state(addons[5]), "true,true,false");
364 do_check_eq(check_plugin_state(PLUGINS[5]), "true,false");
366 // These should have been unchanged
367 do_check_eq(check_addon_state(addons[0]), "true,false,false");
368 do_check_eq(check_addon_state(addons[1]), "false,false,false");
369 do_check_eq(check_addon_state(addons[3]), "true,true,false");
370 do_check_eq(check_addon_state(addons[4]), "false,false,false");
371 do_check_eq(check_addon_state(addons[6]), "false,false,true");
372 do_check_eq(check_plugin_state(PLUGINS[0]), "true,false");
373 do_check_eq(check_plugin_state(PLUGINS[1]), "false,false");
374 do_check_eq(check_plugin_state(PLUGINS[3]), "true,false");
375 do_check_eq(check_plugin_state(PLUGINS[4]), "false,false");
377 // Back to starting state
378 addons[2].userDisabled = false;
379 addons[5].userDisabled = false;
380 PLUGINS[2].enabledState = Ci.nsIPluginTag.STATE_ENABLED;
381 PLUGINS[5].enabledState = Ci.nsIPluginTag.STATE_ENABLED;
382 restartManager();
383 gNotificationCheck = null;
384 gTestCheck = run_test_pt3;
385 load_blocklist("bug455906_start.xml");
386 }));
387 }
389 function run_test_pt3() {
390 restartManager();
391 check_initial_state(function() {
392 gNotificationCheck = check_notification_pt3;
393 gTestCheck = check_test_pt3;
394 load_blocklist("bug455906_block.xml");
395 });
396 }
398 function check_notification_pt3(args) {
399 dump("Checking notification pt 3\n");
400 do_check_eq(args.list.length, 6);
402 for (let addon of args.list) {
403 if (addon.item instanceof Ci.nsIPluginTag) {
404 switch (addon.item.name) {
405 case "test_bug455906_2":
406 do_check_true(addon.blocked);
407 break;
408 case "test_bug455906_3":
409 do_check_true(addon.blocked);
410 break;
411 case "test_bug455906_5":
412 do_check_true(addon.blocked);
413 break;
414 default:
415 do_throw("Unknown addon: " + addon.item.name);
416 }
417 }
418 else {
419 switch (addon.item.id) {
420 case "test_bug455906_2@tests.mozilla.org":
421 do_check_true(addon.blocked);
422 break;
423 case "test_bug455906_3@tests.mozilla.org":
424 do_check_true(addon.blocked);
425 break;
426 case "test_bug455906_5@tests.mozilla.org":
427 do_check_true(addon.blocked);
428 break;
429 default:
430 do_throw("Unknown addon: " + addon.item.id);
431 }
432 }
433 }
434 }
436 function check_test_pt3() {
437 restartManager();
438 dump("Checking results pt 3\n");
440 let blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
441 getService(Ci.nsIBlocklistService);
443 AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) {
444 // All should have gained the blocklist state, user disabled as previously
445 do_check_eq(check_addon_state(addons[0]), "true,false,true");
446 do_check_eq(check_addon_state(addons[1]), "false,false,true");
447 do_check_eq(check_addon_state(addons[2]), "false,false,true");
448 do_check_eq(check_addon_state(addons[4]), "false,false,true");
449 do_check_eq(check_plugin_state(PLUGINS[0]), "true,true");
450 do_check_eq(check_plugin_state(PLUGINS[1]), "false,true");
451 do_check_eq(check_plugin_state(PLUGINS[2]), "false,true");
452 do_check_eq(check_plugin_state(PLUGINS[3]), "true,true");
453 do_check_eq(check_plugin_state(PLUGINS[4]), "false,true");
455 // Should have gained the blocklist state but no longer be soft disabled
456 do_check_eq(check_addon_state(addons[3]), "false,false,true");
458 // Check blockIDs are correct
459 do_check_eq(blocklist.getAddonBlocklistURL(addons[0]),create_blocklistURL(addons[0].id));
460 do_check_eq(blocklist.getAddonBlocklistURL(addons[1]),create_blocklistURL(addons[1].id));
461 do_check_eq(blocklist.getAddonBlocklistURL(addons[2]),create_blocklistURL(addons[2].id));
462 do_check_eq(blocklist.getAddonBlocklistURL(addons[3]),create_blocklistURL(addons[3].id));
463 do_check_eq(blocklist.getAddonBlocklistURL(addons[4]),create_blocklistURL(addons[4].id));
465 // All plugins have the same blockID on the test
466 do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[0]), create_blocklistURL('test_bug455906_plugin'));
467 do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[1]), create_blocklistURL('test_bug455906_plugin'));
468 do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[2]), create_blocklistURL('test_bug455906_plugin'));
469 do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[3]), create_blocklistURL('test_bug455906_plugin'));
470 do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[4]), create_blocklistURL('test_bug455906_plugin'));
472 // Shouldn't be changed
473 do_check_eq(check_addon_state(addons[5]), "false,false,true");
474 do_check_eq(check_addon_state(addons[6]), "false,false,true");
475 do_check_eq(check_plugin_state(PLUGINS[5]), "false,true");
477 // Back to starting state
478 gNotificationCheck = null;
479 gTestCheck = run_test_pt4;
480 load_blocklist("bug455906_start.xml");
481 });
482 }
484 function run_test_pt4() {
485 AddonManager.getAddonByID(ADDONS[4].id, callback_soon(function(addon) {
486 addon.userDisabled = false;
487 PLUGINS[4].enabledState = Ci.nsIPluginTag.STATE_ENABLED;
488 restartManager();
489 check_initial_state(function() {
490 gNotificationCheck = check_notification_pt4;
491 gTestCheck = check_test_pt4;
492 load_blocklist("bug455906_empty.xml");
493 });
494 }));
495 }
497 function check_notification_pt4(args) {
498 dump("Checking notification pt 4\n");
500 // Should be just the dummy add-on to force this notification
501 do_check_eq(args.list.length, 1);
502 do_check_false(args.list[0].item instanceof Ci.nsIPluginTag);
503 do_check_eq(args.list[0].item.id, "dummy_bug455906_2@tests.mozilla.org");
504 }
506 function check_test_pt4() {
507 restartManager();
508 dump("Checking results pt 4\n");
510 AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) {
511 // This should have become unblocked
512 do_check_eq(check_addon_state(addons[5]), "false,false,false");
513 do_check_eq(check_plugin_state(PLUGINS[5]), "false,false");
515 // Should get re-enabled
516 do_check_eq(check_addon_state(addons[3]), "false,false,false");
518 // No change for anything else
519 do_check_eq(check_addon_state(addons[0]), "true,false,false");
520 do_check_eq(check_addon_state(addons[1]), "false,false,false");
521 do_check_eq(check_addon_state(addons[2]), "false,false,false");
522 do_check_eq(check_addon_state(addons[4]), "false,false,false");
523 do_check_eq(check_addon_state(addons[6]), "false,false,true");
524 do_check_eq(check_plugin_state(PLUGINS[0]), "true,false");
525 do_check_eq(check_plugin_state(PLUGINS[1]), "false,false");
526 do_check_eq(check_plugin_state(PLUGINS[2]), "false,false");
527 do_check_eq(check_plugin_state(PLUGINS[3]), "true,false");
528 do_check_eq(check_plugin_state(PLUGINS[4]), "false,false");
530 finish();
531 });
532 }
534 function finish() {
535 gTestserver.stop(do_test_finished);
536 }