Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
1 var rootDir = getRootDirectory(gTestPath);
2 const gTestRoot = rootDir;
3 const gHttpTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
5 var gTestBrowser = null;
6 var gNextTest = null;
7 var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
9 Components.utils.import("resource://gre/modules/Services.jsm");
11 // This listens for the next opened tab and checks it is of the right url.
12 // opencallback is called when the new tab is fully loaded
13 // closecallback is called when the tab is closed
14 function TabOpenListener(url, opencallback, closecallback) {
15 this.url = url;
16 this.opencallback = opencallback;
17 this.closecallback = closecallback;
19 gBrowser.tabContainer.addEventListener("TabOpen", this, false);
20 }
22 TabOpenListener.prototype = {
23 url: null,
24 opencallback: null,
25 closecallback: null,
26 tab: null,
27 browser: null,
29 handleEvent: function(event) {
30 if (event.type == "TabOpen") {
31 gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
32 this.tab = event.originalTarget;
33 this.browser = this.tab.linkedBrowser;
34 gBrowser.addEventListener("pageshow", this, false);
35 } else if (event.type == "pageshow") {
36 if (event.target.location.href != this.url)
37 return;
38 gBrowser.removeEventListener("pageshow", this, false);
39 this.tab.addEventListener("TabClose", this, false);
40 var url = this.browser.contentDocument.location.href;
41 is(url, this.url, "Should have opened the correct tab");
42 this.opencallback(this.tab, this.browser.contentWindow);
43 } else if (event.type == "TabClose") {
44 if (event.originalTarget != this.tab)
45 return;
46 this.tab.removeEventListener("TabClose", this, false);
47 this.opencallback = null;
48 this.tab = null;
49 this.browser = null;
50 // Let the window close complete
51 executeSoon(this.closecallback);
52 this.closecallback = null;
53 }
54 }
55 };
57 function test() {
58 waitForExplicitFinish();
59 requestLongerTimeout(2);
60 registerCleanupFunction(function() {
61 clearAllPluginPermissions();
62 Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
63 Services.prefs.clearUserPref("plugins.hideMissingPluginsNotification");
64 });
65 Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
67 setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
68 setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in");
70 var newTab = gBrowser.addTab();
71 gBrowser.selectedTab = newTab;
72 gTestBrowser = gBrowser.selectedBrowser;
73 gTestBrowser.addEventListener("load", pageLoad, true);
74 prepareTest(runAfterPluginBindingAttached(test1a), gTestRoot + "plugin_unknown.html");
75 }
77 function finishTest() {
78 clearAllPluginPermissions();
79 gTestBrowser.removeEventListener("load", pageLoad, true);
80 gBrowser.removeCurrentTab();
81 window.focus();
82 finish();
83 }
85 function pageLoad() {
86 // The plugin events are async dispatched and can come after the load event
87 // This just allows the events to fire before we then go on to test the states
88 executeSoon(gNextTest);
89 }
91 function prepareTest(nextTest, url) {
92 gNextTest = nextTest;
93 gTestBrowser.contentWindow.location = url;
94 }
96 // Due to layout being async, "PluginBindAttached" may trigger later.
97 // This wraps a function to force a layout flush, thus triggering it,
98 // and schedules the function execution so they're definitely executed
99 // afterwards.
100 function runAfterPluginBindingAttached(func) {
101 return function() {
102 let doc = gTestBrowser.contentDocument;
103 let elems = doc.getElementsByTagName('embed');
104 if (elems.length < 1) {
105 elems = doc.getElementsByTagName('object');
106 }
107 elems[0].clientTop;
108 executeSoon(func);
109 };
110 }
112 // Tests a page with an unknown plugin in it.
113 function test1a() {
114 ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 1a, Should have displayed the missing plugin notification");
115 ok(gTestBrowser.missingPlugins, "Test 1a, Should be a missing plugin list");
116 ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 1a, Should know about application/x-unknown");
117 ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 1a, Should not know about application/x-test");
119 var pluginNode = gTestBrowser.contentDocument.getElementById("unknown");
120 ok(pluginNode, "Test 1a, Found plugin in page");
121 var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
122 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED, "Test 1a, plugin fallback type should be PLUGIN_UNSUPPORTED");
124 Services.prefs.setBoolPref("plugins.hideMissingPluginsNotification", true);
125 prepareTest(runAfterPluginBindingAttached(test1b), gTestRoot + "plugin_unknown.html");
126 }
129 function test1b() {
130 ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 1b, Should not have displayed the missing plugin notification");
131 ok(!gTestBrowser.missingPlugins, "Test 1b, Should not be a missing plugin list");
132 Services.prefs.clearUserPref("plugins.hideMissingPluginsNotification");
134 var plugin = getTestPlugin();
135 ok(plugin, "Test 1b, Should have a test plugin");
136 plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
137 prepareTest(runAfterPluginBindingAttached(test2), gTestRoot + "plugin_test.html");
138 }
140 // Tests a page with a working plugin in it.
141 function test2() {
142 ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 2, Should not have displayed the missing plugin notification");
143 ok(!gTestBrowser.missingPlugins, "Test 2, Should not be a missing plugin list");
145 var plugin = getTestPlugin();
146 ok(plugin, "Should have a test plugin");
147 plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
148 prepareTest(runAfterPluginBindingAttached(test3), gTestRoot + "plugin_test.html");
149 }
151 // Tests a page with a disabled plugin in it.
152 function test3() {
153 ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 3, Should not have displayed the missing plugin notification");
154 ok(!gTestBrowser.missingPlugins, "Test 3, Should not be a missing plugin list");
156 new TabOpenListener("about:addons", test4, prepareTest5);
158 var pluginNode = gTestBrowser.contentDocument.getElementById("test");
159 ok(pluginNode, "Test 3, Found plugin in page");
160 var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
161 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED, "Test 3, plugin fallback type should be PLUGIN_DISABLED");
162 var manageLink = gTestBrowser.contentDocument.getAnonymousElementByAttribute(pluginNode, "anonid", "managePluginsLink");
163 ok(manageLink, "Test 3, found 'manage' link in plugin-problem binding");
165 EventUtils.synthesizeMouseAtCenter(manageLink, {}, gTestBrowser.contentWindow);
166 }
168 function test4(tab, win) {
169 is(win.wrappedJSObject.gViewController.currentViewId, "addons://list/plugin", "Test 4, Should have displayed the plugins pane");
170 gBrowser.removeTab(tab);
171 }
173 function prepareTest5() {
174 info("prepareTest5");
175 var plugin = getTestPlugin();
176 plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
177 setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml",
178 function() {
179 info("prepareTest5 callback");
180 prepareTest(runAfterPluginBindingAttached(test5), gTestRoot + "plugin_test.html");
181 });
182 }
184 // Tests a page with a blocked plugin in it.
185 function test5() {
186 info("test5");
187 ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 5, Should not have displayed the missing plugin notification");
188 let notification = PopupNotifications.getNotification("click-to-play-plugins");
189 ok(notification, "Test 5: There should be a plugin notification for blocked plugins");
190 ok(notification.dismissed, "Test 5: The plugin notification should be dismissed by default");
192 notification.reshow();
193 is(notification.options.pluginData.size, 1, "Test 5: Only the blocked plugin should be present in the notification");
194 ok(PopupNotifications.panel.firstChild._buttonContainer.hidden, "Part 5: The blocked plugins notification should not have any buttons visible.");
196 ok(!gTestBrowser.missingPlugins, "Test 5, Should not be a missing plugin list");
197 var pluginNode = gTestBrowser.contentDocument.getElementById("test");
198 ok(pluginNode, "Test 5, Found plugin in page");
199 var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
200 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, "Test 5, plugin fallback type should be PLUGIN_BLOCKLISTED");
202 prepareTest(runAfterPluginBindingAttached(test6), gTestRoot + "plugin_both.html");
203 }
205 // Tests a page with a blocked and unknown plugin in it.
206 function test6() {
207 ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 6, Should have displayed the missing plugin notification");
208 ok(gTestBrowser.missingPlugins, "Test 6, Should be a missing plugin list");
209 ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 6, Should know about application/x-unknown");
210 ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 6, application/x-test should not be a missing plugin");
212 prepareTest(runAfterPluginBindingAttached(test7), gTestRoot + "plugin_both2.html");
213 }
215 // Tests a page with a blocked and unknown plugin in it (alternate order to above).
216 function test7() {
217 ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 7, Should have displayed the missing plugin notification");
218 ok(gTestBrowser.missingPlugins, "Test 7, Should be a missing plugin list");
219 ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 7, Should know about application/x-unknown");
220 ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 7, application/x-test should not be a missing plugin");
222 var plugin = getTestPlugin();
223 plugin.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
224 getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
226 setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() {
227 prepareTest(runAfterPluginBindingAttached(test8), gTestRoot + "plugin_test.html");
228 });
229 }
231 // Tests a page with a working plugin that is click-to-play
232 function test8() {
233 ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 8, Should not have displayed the missing plugin notification");
234 ok(!gTestBrowser.missingPlugins, "Test 8, Should not be a missing plugin list");
235 ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 8, Should have a click-to-play notification");
237 var pluginNode = gTestBrowser.contentDocument.getElementById("test");
238 ok(pluginNode, "Test 8, Found plugin in page");
239 var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
240 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 8, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
242 prepareTest(runAfterPluginBindingAttached(test11a), gTestRoot + "plugin_test3.html");
243 }
245 // Tests 9 & 10 removed
247 // Tests that the going back will reshow the notification for click-to-play plugins (part 1/4)
248 function test11a() {
249 var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
250 ok(popupNotification, "Test 11a, Should have a click-to-play notification");
252 prepareTest(test11b, "about:blank");
253 }
255 // Tests that the going back will reshow the notification for click-to-play plugins (part 2/4)
256 function test11b() {
257 var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
258 ok(!popupNotification, "Test 11b, Should not have a click-to-play notification");
260 Services.obs.addObserver(test11c, "PopupNotifications-updateNotShowing", false);
261 gTestBrowser.contentWindow.history.back();
262 }
264 // Tests that the going back will reshow the notification for click-to-play plugins (part 3/4)
265 function test11c() {
266 Services.obs.removeObserver(test11c, "PopupNotifications-updateNotShowing");
267 var condition = function() PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
268 waitForCondition(condition, test11d, "Test 11c, waited too long for click-to-play-plugin notification");
269 }
271 // Tests that the going back will reshow the notification for click-to-play plugins (part 4/4)
272 function test11d() {
273 var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
274 ok(popupNotification, "Test 11d, Should have a click-to-play notification");
276 prepareTest(runAfterPluginBindingAttached(test12a), gHttpTestRoot + "plugin_clickToPlayAllow.html");
277 }
279 // Tests that the "Allow Always" permission works for click-to-play plugins
280 function test12a() {
281 var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
282 ok(popupNotification, "Test 12a, Should have a click-to-play notification");
283 var plugin = gTestBrowser.contentDocument.getElementById("test");
284 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
285 ok(!objLoadingContent.activated, "Test 12a, Plugin should not be activated");
287 // Simulate clicking the "Allow Always" button.
288 popupNotification.reshow();
289 PopupNotifications.panel.firstChild._primaryButton.click();
291 var condition = function() objLoadingContent.activated;
292 waitForCondition(condition, test12b, "Test 12a, Waited too long for plugin to activate");
293 }
295 function test12b() {
296 var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
297 ok(popupNotification, "Test 12d, Should have a click-to-play notification");
298 prepareTest(runAfterPluginBindingAttached(test12c), gHttpTestRoot + "plugin_two_types.html");
299 }
301 // Test that the "Always" permission, when set for just the Test plugin,
302 // does not also allow the Second Test plugin.
303 function test12c() {
304 var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
305 ok(popupNotification, "Test 12d, Should have a click-to-play notification");
306 var test = gTestBrowser.contentDocument.getElementById("test");
307 var secondtestA = gTestBrowser.contentDocument.getElementById("secondtestA");
308 var secondtestB = gTestBrowser.contentDocument.getElementById("secondtestB");
309 ok(test.activated, "Test 12d, Test plugin should be activated");
310 ok(!secondtestA.activated, "Test 12d, Second Test plugin (A) should not be activated");
311 ok(!secondtestB.activated, "Test 12d, Second Test plugin (B) should not be activated");
313 clearAllPluginPermissions();
314 var plugin = getTestPlugin();
315 plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
316 prepareTest(test14, gTestRoot + "plugin_test2.html");
317 }
319 // Test 13 removed
321 // Tests that the plugin's "activated" property is true for working plugins with click-to-play disabled.
322 function test14() {
323 var plugin = gTestBrowser.contentDocument.getElementById("test1");
324 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
325 ok(objLoadingContent.activated, "Test 14, Plugin should be activated");
327 var plugin = getTestPlugin();
328 plugin.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
329 getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
330 prepareTest(runAfterPluginBindingAttached(test15), gTestRoot + "plugin_alternate_content.html");
331 }
333 // Tests that the overlay is shown instead of alternate content when
334 // plugins are click to play
335 function test15() {
336 var plugin = gTestBrowser.contentDocument.getElementById("test");
337 var doc = gTestBrowser.contentDocument;
338 var mainBox = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
339 ok(mainBox, "Test 15, Plugin with id=" + plugin.id + " overlay should exist");
341 prepareTest(runAfterPluginBindingAttached(test17), gTestRoot + "plugin_bug749455.html");
342 }
344 // Test 16 removed
346 // Tests that mContentType is used for click-to-play plugins, and not the
347 // inspected type.
348 function test17() {
349 var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
350 ok(clickToPlayNotification, "Test 17, Should have a click-to-play notification");
351 var missingNotification = PopupNotifications.getNotification("missing-plugins", gTestBrowser);
352 ok(!missingNotification, "Test 17, Should not have a missing plugin notification");
354 setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
355 function() {
356 prepareTest(runAfterPluginBindingAttached(test18a), gHttpTestRoot + "plugin_test.html");
357 });
358 }
360 // Tests a vulnerable, updatable plugin
361 function test18a() {
362 var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
363 ok(clickToPlayNotification, "Test 18a, Should have a click-to-play notification");
364 var doc = gTestBrowser.contentDocument;
365 var plugin = doc.getElementById("test");
366 ok(plugin, "Test 18a, Found plugin in page");
367 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
368 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "Test 18a, plugin fallback type should be PLUGIN_VULNERABLE_UPDATABLE");
369 ok(!objLoadingContent.activated, "Test 18a, Plugin should not be activated");
370 var overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
371 ok(overlay.classList.contains("visible"), "Test 18a, Plugin overlay should exist, not be hidden");
372 var updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
373 ok(updateLink.style.visibility != "hidden", "Test 18a, Plugin should have an update link");
375 var tabOpenListener = new TabOpenListener(Services.urlFormatter.formatURLPref("plugins.update.url"), false, false);
376 tabOpenListener.handleEvent = function(event) {
377 if (event.type == "TabOpen") {
378 gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
379 this.tab = event.originalTarget;
380 is(event.target.label, this.url, "Test 18a, Update link should open up the plugin check page");
381 gBrowser.removeTab(this.tab);
382 test18b();
383 }
384 };
385 EventUtils.synthesizeMouseAtCenter(updateLink, {}, gTestBrowser.contentWindow);
386 }
388 function test18b() {
389 // clicking the update link should not activate the plugin
390 var doc = gTestBrowser.contentDocument;
391 var plugin = doc.getElementById("test");
392 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
393 ok(!objLoadingContent.activated, "Test 18b, Plugin should not be activated");
394 var overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
395 ok(overlay.classList.contains("visible"), "Test 18b, Plugin overlay should exist, not be hidden");
397 setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableNoUpdate.xml",
398 function() {
399 prepareTest(runAfterPluginBindingAttached(test18c), gHttpTestRoot + "plugin_test.html");
400 });
401 }
403 // Tests a vulnerable plugin with no update
404 function test18c() {
405 var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
406 ok(clickToPlayNotification, "Test 18c, Should have a click-to-play notification");
407 var doc = gTestBrowser.contentDocument;
408 var plugin = doc.getElementById("test");
409 ok(plugin, "Test 18c, Found plugin in page");
410 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
411 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE, "Test 18c, plugin fallback type should be PLUGIN_VULNERABLE_NO_UPDATE");
412 ok(!objLoadingContent.activated, "Test 18c, Plugin should not be activated");
413 var overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
414 ok(overlay.classList.contains("visible"), "Test 18c, Plugin overlay should exist, not be hidden");
415 var updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
416 ok(updateLink.style.display != "block", "Test 18c, Plugin should not have an update link");
418 // check that click "Always allow" works with blocklisted plugins
419 clickToPlayNotification.reshow();
420 PopupNotifications.panel.firstChild._primaryButton.click();
422 var condition = function() objLoadingContent.activated;
423 waitForCondition(condition, test18d, "Test 18d, Waited too long for plugin to activate");
424 }
426 // continue testing "Always allow"
427 function test18d() {
428 var plugin = gTestBrowser.contentDocument.getElementById("test");
429 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
430 ok(objLoadingContent.activated, "Test 18d, Plugin should be activated");
432 prepareTest(test18e, gHttpTestRoot + "plugin_test.html");
433 }
435 // continue testing "Always allow"
436 function test18e() {
437 var plugin = gTestBrowser.contentDocument.getElementById("test");
438 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
439 ok(objLoadingContent.activated, "Test 18e, Plugin should be activated");
441 clearAllPluginPermissions();
442 prepareTest(runAfterPluginBindingAttached(test18f), gHttpTestRoot + "plugin_test.html");
443 }
445 // clicking the in-content overlay of a vulnerable plugin should bring
446 // up the notification and not directly activate the plugin
447 function test18f() {
448 var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
449 ok(notification, "Test 18f, Should have a click-to-play notification");
450 ok(notification.dismissed, "Test 18f, notification should start dismissed");
451 var plugin = gTestBrowser.contentDocument.getElementById("test");
452 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
453 ok(!objLoadingContent.activated, "Test 18f, Plugin should not be activated");
455 var oldEventCallback = notification.options.eventCallback;
456 notification.options.eventCallback = function() {
457 oldEventCallback();
458 executeSoon(test18g);
459 };
460 EventUtils.synthesizeMouseAtCenter(plugin, {}, gTestBrowser.contentWindow);
461 }
463 function test18g() {
464 var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
465 ok(notification, "Test 18g, Should have a click-to-play notification");
466 ok(!notification.dismissed, "Test 18g, notification should be open");
467 notification.options.eventCallback = null;
468 var plugin = gTestBrowser.contentDocument.getElementById("test");
469 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
470 ok(!objLoadingContent.activated, "Test 18g, Plugin should not be activated");
472 setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml",
473 function() {
474 resetBlocklist();
475 prepareTest(runAfterPluginBindingAttached(test19a), gTestRoot + "plugin_test.html");
476 });
477 }
479 // Tests that clicking the icon of the overlay activates the doorhanger
480 function test19a() {
481 var doc = gTestBrowser.contentDocument;
482 var plugin = doc.getElementById("test");
483 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
484 ok(!objLoadingContent.activated, "Test 19a, Plugin should not be activated");
485 ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, "Test 19a, Doorhanger should start out dismissed");
487 var icon = doc.getAnonymousElementByAttribute(plugin, "class", "icon");
488 EventUtils.synthesizeMouseAtCenter(icon, {}, gTestBrowser.contentWindow);
489 let condition = function() !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
490 waitForCondition(condition, test19b, "Test 19a, Waited too long for doorhanger to activate");
491 }
493 function test19b() {
494 prepareTest(runAfterPluginBindingAttached(test19c), gTestRoot + "plugin_test.html");
495 }
497 // Tests that clicking the text of the overlay activates the plugin
498 function test19c() {
499 var doc = gTestBrowser.contentDocument;
500 var plugin = doc.getElementById("test");
501 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
502 ok(!objLoadingContent.activated, "Test 19c, Plugin should not be activated");
504 ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, "Test 19c, Doorhanger should start out dismissed");
506 var text = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay");
507 EventUtils.synthesizeMouseAtCenter(text, {}, gTestBrowser.contentWindow);
508 let condition = function() !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
509 waitForCondition(condition, test19d, "Test 19c, Waited too long for doorhanger to activate");
510 }
512 function test19d() {
513 prepareTest(runAfterPluginBindingAttached(test19e), gTestRoot + "plugin_test.html");
514 }
516 // Tests that clicking the box of the overlay activates the doorhanger
517 // (just to be thorough)
518 function test19e() {
519 var doc = gTestBrowser.contentDocument;
520 var plugin = doc.getElementById("test");
521 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
522 ok(!objLoadingContent.activated, "Test 19e, Plugin should not be activated");
524 ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, "Test 19e, Doorhanger should start out dismissed");
526 EventUtils.synthesizeMouse(plugin, 50, 50, {}, gTestBrowser.contentWindow);
527 let condition = function() !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
528 waitForCondition(condition, test19f, "Test 19e, Waited too long for plugin to activate");
529 }
531 function test19f() {
532 prepareTest(test20a, gTestRoot + "plugin_hidden_to_visible.html");
533 }
535 // Tests that a plugin in a div that goes from style="display: none" to
536 // "display: block" can be clicked to activate.
537 function test20a() {
538 var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
539 ok(!clickToPlayNotification, "Test 20a, Should not have a click-to-play notification");
540 var doc = gTestBrowser.contentDocument;
541 var plugin = doc.getElementById("plugin");
542 var mainBox = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
543 ok(mainBox, "Test 20a, plugin overlay should not be null");
544 var pluginRect = mainBox.getBoundingClientRect();
545 ok(pluginRect.width == 0, "Test 20a, plugin should have an overlay with 0px width");
546 ok(pluginRect.height == 0, "Test 20a, plugin should have an overlay with 0px height");
547 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
548 ok(!objLoadingContent.activated, "Test 20a, plugin should not be activated");
549 var div = doc.getElementById("container");
550 ok(div.style.display == "none", "Test 20a, container div should be display: none");
552 div.style.display = "block";
553 var condition = function() {
554 var pluginRect = mainBox.getBoundingClientRect();
555 return (pluginRect.width == 200);
556 }
557 waitForCondition(condition, test20b, "Test 20a, Waited too long for plugin to become visible");
558 }
560 function test20b() {
561 var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
562 ok(clickToPlayNotification, "Test 20b, Should now have a click-to-play notification");
563 var doc = gTestBrowser.contentDocument;
564 var plugin = doc.getElementById("plugin");
565 var pluginRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
566 ok(pluginRect.width == 200, "Test 20b, plugin should have an overlay with 200px width");
567 ok(pluginRect.height == 200, "Test 20b, plugin should have an overlay with 200px height");
568 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
569 ok(!objLoadingContent.activated, "Test 20b, plugin should not be activated");
571 ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, "Test 20b, Doorhanger should start out dismissed");
573 EventUtils.synthesizeMouseAtCenter(plugin, {}, gTestBrowser.contentWindow);
574 let condition = function() !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
575 waitForCondition(condition, test20c, "Test 20b, Waited too long for plugin to activate");
576 }
578 function test20c() {
579 PopupNotifications.panel.firstChild._primaryButton.click();
580 var doc = gTestBrowser.contentDocument;
581 var plugin = doc.getElementById("plugin");
582 let condition = function() plugin.activated;
583 waitForCondition(condition, test20d, "Test 20c", "Waiting for plugin to activate");
584 }
586 function test20d() {
587 var doc = gTestBrowser.contentDocument;
588 var plugin = doc.getElementById("plugin");
589 var pluginRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
590 ok(pluginRect.width == 0, "Test 20d, plugin should have click-to-play overlay with zero width");
591 ok(pluginRect.height == 0, "Test 20d, plugin should have click-to-play overlay with zero height");
592 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
593 ok(objLoadingContent.activated, "Test 20d, plugin should be activated");
595 clearAllPluginPermissions();
597 prepareTest(runAfterPluginBindingAttached(test21a), gTestRoot + "plugin_two_types.html");
598 }
600 // Test having multiple different types of plugin on one page
601 function test21a() {
602 var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
603 ok(notification, "Test 21a, Should have a click-to-play notification");
605 var doc = gTestBrowser.contentDocument;
606 var ids = ["test", "secondtestA", "secondtestB"];
607 for (var id of ids) {
608 var plugin = doc.getElementById(id);
609 var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
610 ok(rect.width == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
611 ok(rect.height == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
612 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
613 ok(!objLoadingContent.activated, "Test 21a, Plugin with id=" + plugin.id + " should not be activated");
614 }
616 // we have to actually show the panel to get the bindings to instantiate
617 notification.reshow();
618 is(notification.options.pluginData.size, 2, "Test 21a, Should have two types of plugin in the notification");
620 var centerAction = null;
621 for (var action of notification.options.pluginData.values()) {
622 if (action.pluginName == "Test") {
623 centerAction = action;
624 break;
625 }
626 }
627 ok(centerAction, "Test 21b, found center action for the Test plugin");
629 var centerItem = null;
630 for (var item of PopupNotifications.panel.firstChild.childNodes) {
631 is(item.value, "block", "Test 21b, all plugins should start out blocked");
632 if (item.action == centerAction) {
633 centerItem = item;
634 break;
635 }
636 }
637 ok(centerItem, "Test 21b, found center item for the Test plugin");
639 // "click" the button to activate the Test plugin
640 centerItem.value = "allownow";
641 PopupNotifications.panel.firstChild._primaryButton.click();
643 var doc = gTestBrowser.contentDocument;
644 var plugin = doc.getElementById("test");
645 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
646 var condition = function() objLoadingContent.activated;
647 waitForCondition(condition, test21c, "Test 21b, Waited too long for plugin to activate");
648 }
650 function test21c() {
651 var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
652 ok(notification, "Test 21c, Should have a click-to-play notification");
654 notification.reshow();
655 ok(notification.options.pluginData.size == 2, "Test 21c, Should have one type of plugin in the notification");
657 var doc = gTestBrowser.contentDocument;
658 var plugin = doc.getElementById("test");
659 var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
660 ok(rect.width == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
661 ok(rect.height == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
662 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
663 ok(objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should be activated");
665 var ids = ["secondtestA", "secondtestB"];
666 for (var id of ids) {
667 var plugin = doc.getElementById(id);
668 var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
669 ok(rect.width == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
670 ok(rect.height == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
671 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
672 ok(!objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should not be activated");
673 }
675 var centerAction = null;
676 for (var action of notification.options.pluginData.values()) {
677 if (action.pluginName == "Second Test") {
678 centerAction = action;
679 break;
680 }
681 }
682 ok(centerAction, "Test 21d, found center action for the Second Test plugin");
684 var centerItem = null;
685 for (var item of PopupNotifications.panel.firstChild.childNodes) {
686 if (item.action == centerAction) {
687 is(item.value, "block", "Test 21d, test plugin 2 should start blocked");
688 centerItem = item;
689 break;
690 }
691 else {
692 is(item.value, "allownow", "Test 21d, test plugin should be enabled");
693 }
694 }
695 ok(centerItem, "Test 21d, found center item for the Second Test plugin");
697 // "click" the button to activate the Second Test plugins
698 centerItem.value = "allownow";
699 PopupNotifications.panel.firstChild._primaryButton.click();
701 var doc = gTestBrowser.contentDocument;
702 var plugin = doc.getElementById("secondtestA");
703 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
704 var condition = function() objLoadingContent.activated;
705 waitForCondition(condition, test21e, "Test 21d, Waited too long for plugin to activate");
706 }
708 function test21e() {
709 var doc = gTestBrowser.contentDocument;
710 var ids = ["test", "secondtestA", "secondtestB"];
711 for (var id of ids) {
712 var plugin = doc.getElementById(id);
713 var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
714 ok(rect.width == 0, "Test 21e, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
715 ok(rect.height == 0, "Test 21e, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
716 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
717 ok(objLoadingContent.activated, "Test 21e, Plugin with id=" + plugin.id + " should be activated");
718 }
720 getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
721 getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
723 clearAllPluginPermissions();
725 prepareTest(runAfterPluginBindingAttached(test22), gTestRoot + "plugin_test.html");
726 }
728 // Tests that a click-to-play plugin retains its activated state upon reloading
729 function test22() {
730 ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 22, Should have a click-to-play notification");
732 // Plugin should start as CTP
733 var pluginNode = gTestBrowser.contentDocument.getElementById("test");
734 ok(pluginNode, "Test 22, Found plugin in page");
735 var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
736 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 22, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
738 // Activate
739 objLoadingContent.playPlugin();
740 is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, plugin should have started");
741 ok(pluginNode.activated, "Test 22, plugin should be activated");
743 // Spin event loop for plugin to finish spawning
744 executeSoon(function() {
745 var oldVal = pluginNode.getObjectValue();
746 pluginNode.src = pluginNode.src;
747 is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, Plugin should have retained activated state");
748 ok(pluginNode.activated, "Test 22, plugin should have remained activated");
749 // Sanity, ensure that we actually reloaded the instance, since this behavior might change in the future.
750 var pluginsDiffer;
751 try {
752 pluginNode.checkObjectValue(oldVal);
753 } catch (e) {
754 pluginsDiffer = true;
755 }
756 ok(pluginsDiffer, "Test 22, plugin should have reloaded");
758 prepareTest(runAfterPluginBindingAttached(test23), gTestRoot + "plugin_test.html");
759 });
760 }
762 // Tests that a click-to-play plugin resets its activated state when changing types
763 function test23() {
764 ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 23, Should have a click-to-play notification");
766 // Plugin should start as CTP
767 var pluginNode = gTestBrowser.contentDocument.getElementById("test");
768 ok(pluginNode, "Test 23, Found plugin in page");
769 var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
770 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 23, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
772 // Activate
773 objLoadingContent.playPlugin();
774 is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 23, plugin should have started");
775 ok(pluginNode.activated, "Test 23, plugin should be activated");
777 // Reload plugin (this may need RunSoon() in the future when plugins change state asynchronously)
778 pluginNode.type = null;
779 // We currently don't properly change state just on type change,
780 // so rebind the plugin to tree. bug 767631
781 pluginNode.parentNode.appendChild(pluginNode);
782 is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, plugin should be unloaded");
783 pluginNode.type = "application/x-test";
784 pluginNode.parentNode.appendChild(pluginNode);
785 is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, Plugin should not have activated");
786 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 23, Plugin should be click-to-play");
787 ok(!pluginNode.activated, "Test 23, plugin node should not be activated");
789 prepareTest(runAfterPluginBindingAttached(test24a), gHttpTestRoot + "plugin_test.html");
790 }
792 // Test that "always allow"-ing a plugin will not allow it when it becomes
793 // blocklisted.
794 function test24a() {
795 var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
796 ok(notification, "Test 24a, Should have a click-to-play notification");
797 var plugin = gTestBrowser.contentDocument.getElementById("test");
798 ok(plugin, "Test 24a, Found plugin in page");
799 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
800 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 24a, Plugin should be click-to-play");
801 ok(!objLoadingContent.activated, "Test 24a, plugin should not be activated");
803 // simulate "always allow"
804 notification.reshow();
805 PopupNotifications.panel.firstChild._primaryButton.click();
806 prepareTest(test24b, gHttpTestRoot + "plugin_test.html");
807 }
809 // did the "always allow" work as intended?
810 function test24b() {
811 var plugin = gTestBrowser.contentDocument.getElementById("test");
812 ok(plugin, "Test 24b, Found plugin in page");
813 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
814 ok(objLoadingContent.activated, "Test 24b, plugin should be activated");
815 setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
816 function() {
817 prepareTest(runAfterPluginBindingAttached(test24c), gHttpTestRoot + "plugin_test.html");
818 });
819 }
821 // the plugin is now blocklisted, so it should not automatically load
822 function test24c() {
823 var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
824 ok(notification, "Test 24c, Should have a click-to-play notification");
825 var plugin = gTestBrowser.contentDocument.getElementById("test");
826 ok(plugin, "Test 24c, Found plugin in page");
827 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
828 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "Test 24c, Plugin should be vulnerable/updatable");
829 ok(!objLoadingContent.activated, "Test 24c, plugin should not be activated");
831 // simulate "always allow"
832 notification.reshow();
833 PopupNotifications.panel.firstChild._primaryButton.click();
835 prepareTest(test24d, gHttpTestRoot + "plugin_test.html");
836 }
838 // We should still be able to always allow a plugin after we've seen that it's
839 // blocklisted.
840 function test24d() {
841 var plugin = gTestBrowser.contentDocument.getElementById("test");
842 ok(plugin, "Test 24d, Found plugin in page");
843 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
844 ok(objLoadingContent.activated, "Test 24d, plugin should be activated");
846 // this resets the vulnerable plugin permission
847 setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml",
848 function() {
849 clearAllPluginPermissions();
850 resetBlocklist();
851 prepareTest(test25, gTestRoot + "plugin_syncRemoved.html");
852 });
853 }
855 function test25() {
856 let notification = PopupNotifications.getNotification("click-to-play-plugins");
857 ok(notification, "Test 25: There should be a plugin notification even if the plugin was immediately removed");
858 ok(notification.dismissed, "Test 25: The notification should be dismissed by default");
860 finishTest();
861 }