Bug 896965 - Trigger "PluginBindingAttached" before running plugin notification tests. r=keeler, a=bajaj
authorGeorg Fritzsche <georg.fritzsche@googlemail.com>
Mon, 05 Aug 2013 14:58:02 +0200
changeset 153661 13a012060eb945cd64994adf73fe66c4abaa12f1
parent 153660 42bd5e547c30480ca0e38335837630a3f0a106fe
child 153662 1f0fb0b3411f4f5a4efca70a857e75b3a350cd62
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler, bajaj
bugs896965
milestone25.0a2
Bug 896965 - Trigger "PluginBindingAttached" before running plugin notification tests. r=keeler, a=bajaj
browser/base/content/test/browser_CTP_data_urls.js
browser/base/content/test/browser_bug752516.js
browser/base/content/test/browser_bug787619.js
browser/base/content/test/browser_bug812562.js
browser/base/content/test/browser_bug818118.js
browser/base/content/test/browser_pluginnotification.js
--- a/browser/base/content/test/browser_CTP_data_urls.js
+++ b/browser/base/content/test/browser_CTP_data_urls.js
@@ -90,26 +90,42 @@ function pageLoad() {
   executeSoon(gNextTest);
 }
 
 function prepareTest(nextTest, url) {
   gNextTest = nextTest;
   gTestBrowser.contentWindow.location = url;
 }
 
+// Due to layout being async, "PluginBindAttached" may trigger later.
+// This wraps a function to force a layout flush, thus triggering it,
+// and schedules the function execution so they're definitely executed
+// afterwards.
+function runAfterPluginBindingAttached(func) {
+  let doc = gTestBrowser.contentDocument;
+  return function() {
+    let elems = doc.getElementsByTagName('embed');
+    if (elems.length < 1) {
+      elems = doc.getElementsByTagName('object');
+    }
+    elems[0].clientTop;
+    executeSoon(func);
+  };
+}
+
 // Test that the click-to-play doorhanger still works when navigating to data URLs
 function test1a() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 1a, Should have a click-to-play notification");
 
   let plugin = gTestBrowser.contentDocument.getElementById("test");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated");
 
-  gNextTest = test1b;
+  gNextTest = runAfterPluginBindingAttached(test1b);
   gTestBrowser.contentDocument.getElementById("data-link-1").click();
 }
 
 function test1b() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 1b, Should have a click-to-play notification");
 
   let plugin = gTestBrowser.contentDocument.getElementById("test");
@@ -121,28 +137,28 @@ function test1b() {
   PopupNotifications.panel.firstChild._primaryButton.click();
 
   let condition = function() objLoadingContent.activated;
   waitForCondition(condition, test1c, "Test 1b, Waited too long for plugin to activate");
 }
 
 function test1c() {
   clearAllPluginPermissions();
-  prepareTest(test2a, gHttpTestRoot + "plugin_data_url.html");
+  prepareTest(runAfterPluginBindingAttached(test2a), gHttpTestRoot + "plugin_data_url.html");
 }
 
 // Test that the click-to-play notification doesn't break when navigating to data URLs with multiple plugins
 function test2a() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 2a, Should have a click-to-play notification");
   let plugin = gTestBrowser.contentDocument.getElementById("test");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 2a, Plugin should not be activated");
 
-  gNextTest = test2b;
+  gNextTest = runAfterPluginBindingAttached(test2b);
   gTestBrowser.contentDocument.getElementById("data-link-2").click();
 }
 
 function test2b() {
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 2b, Should have a click-to-play notification");
 
   // Simulate choosing "Allow now" for the test plugin
@@ -179,17 +195,17 @@ function test2b() {
 }
 
 function test2c() {
   let plugin = gTestBrowser.contentDocument.getElementById("test1");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 2c, Plugin should be activated");
 
   clearAllPluginPermissions();
-  prepareTest(test3a, gHttpTestRoot + "plugin_data_url.html");
+  prepareTest(runAfterPluginBindingAttached(test3a), gHttpTestRoot + "plugin_data_url.html");
 }
 
 // Test that when navigating to a data url, the plugin permission is inherited
 function test3a() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 3a, Should have a click-to-play notification");
   let plugin = gTestBrowser.contentDocument.getElementById("test");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
@@ -209,17 +225,18 @@ function test3b() {
 }
 
 function test3c() {
   let plugin = gTestBrowser.contentDocument.getElementById("test");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 3c, Plugin should be activated");
 
   clearAllPluginPermissions();
-  prepareTest(test4b, 'data:text/html,<embed id="test" style="width: 200px; height: 200px" type="application/x-test"/>');
+  prepareTest(runAfterPluginBindingAttached(test4b),
+              'data:text/html,<embed id="test" style="width: 200px; height: 200px" type="application/x-test"/>');
 }
 
 // Test that the click-to-play doorhanger still works when directly navigating to data URLs
 function test4a() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 4a, Should have a click-to-play notification");
   let plugin = gTestBrowser.contentDocument.getElementById("test");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
--- a/browser/base/content/test/browser_bug752516.js
+++ b/browser/base/content/test/browser_bug752516.js
@@ -24,18 +24,20 @@ function test() {
   gTestBrowser = gBrowser.selectedBrowser;
   let gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
   gTestBrowser.contentWindow.location = gHttpTestRoot + "plugin_bug752516.html";
 
   gTestBrowser.addEventListener("load", tabLoad, true);
 }
 
 function tabLoad() {
-  // The plugin events are async dispatched and can come after the load event
-  // This just allows the events to fire before we proceed
+  // Due to layout being async, "PluginBindAttached" may trigger later.
+  // This forces a layout flush, thus triggering it, and schedules the
+  // test so it is definitely executed afterwards.
+  gTestBrowser.contentDocument.getElementById('test').clientTop;
   executeSoon(actualTest);
 }
 
 function actualTest() {
   let doc = gTestBrowser.contentDocument;
   let plugin = doc.getElementById("test");
   ok(!plugin.activated, "Plugin should not be activated");
   ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, "Doorhanger should not be open");
--- a/browser/base/content/test/browser_bug787619.js
+++ b/browser/base/content/test/browser_bug787619.js
@@ -16,16 +16,20 @@ function test() {
 
   gBrowser.selectedTab = gBrowser.addTab();
   gTestBrowser = gBrowser.selectedBrowser;
   gTestBrowser.addEventListener("load", pageLoad, true);
   gTestBrowser.contentWindow.location = gHttpTestRoot + "plugin_bug787619.html";
 }
 
 function pageLoad() {
+  // Due to layout being async, "PluginBindAttached" may trigger later.
+  // This forces a layout flush, thus triggering it, and schedules the
+  // test so it is definitely executed afterwards.
+  gTestBrowser.contentDocument.getElementById('plugin').clientTop;
   executeSoon(part1);
 }
 
 function part1() {
   let wrapper = gTestBrowser.contentDocument.getElementById('wrapper');
   wrapper.addEventListener('click', function() ++gWrapperClickCount, false);
 
   let plugin = gTestBrowser.contentDocument.getElementById('plugin');
--- a/browser/base/content/test/browser_bug812562.js
+++ b/browser/base/content/test/browser_bug812562.js
@@ -16,17 +16,24 @@ function test() {
   plugin.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
 
   var newTab = gBrowser.addTab();
   gBrowser.selectedTab = newTab;
   gTestBrowser = gBrowser.selectedBrowser;
   gTestBrowser.addEventListener("load", pageLoad, true);
   setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
   function() {
-    prepareTest(testPart1, gHttpTestRoot + "plugin_test.html");
+    prepareTest(function() {
+        // Due to layout being async, "PluginBindAttached" may trigger later.
+        // This forces a layout flush, thus triggering it, and schedules the
+        // test so it is definitely executed afterwards.
+        gTestBrowser.contentDocument.getElementById('test').clientTop;
+        testPart1();
+      },
+      gHttpTestRoot + "plugin_test.html");
   });
 }
 
 function finishTest() {
   gTestBrowser.removeEventListener("load", pageLoad, true);
   gBrowser.removeCurrentTab();
   window.focus();
   setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml",
--- a/browser/base/content/test/browser_bug818118.js
+++ b/browser/base/content/test/browser_bug818118.js
@@ -18,18 +18,20 @@ function test() {
 
   gBrowser.selectedTab = gBrowser.addTab();
   gTestBrowser = gBrowser.selectedBrowser;
   gTestBrowser.addEventListener("load", pageLoad, true);
   gTestBrowser.contentWindow.location = gHttpTestRoot + "plugin_both.html";
 }
 
 function pageLoad(aEvent) {
-  // The plugin events are async dispatched and can come after the load event
-  // This just allows the events to fire before we then go on to test the states
+  // Due to layout being async, "PluginBindAttached" may trigger later.
+  // This forces a layout flush, thus triggering it, and schedules the
+  // test so it is definitely executed afterwards.
+  gTestBrowser.contentDocument.getElementById('test').clientTop;
   executeSoon(actualTest);
 }
 
 function actualTest() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "should have a click-to-play notification");
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   ok(plugin, "should have known plugin in page");
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -89,43 +89,59 @@ function pageLoad() {
   executeSoon(gNextTest);
 }
 
 function prepareTest(nextTest, url) {
   gNextTest = nextTest;
   gTestBrowser.contentWindow.location = url;
 }
 
+// Due to layout being async, "PluginBindAttached" may trigger later.
+// This wraps a function to force a layout flush, thus triggering it,
+// and schedules the function execution so they're definitely executed
+// afterwards.
+function runAfterPluginBindingAttached(func) {
+  let doc = gTestBrowser.contentDocument;
+  return function() {
+    let elems = doc.getElementsByTagName('embed');
+    if (elems.length < 1) {
+      elems = doc.getElementsByTagName('object');
+    }
+    elems[0].clientTop;
+    executeSoon(func);
+  };
+}
+
 // Tests a page with an unknown plugin in it.
 function test1() {
   ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 1, Should have displayed the missing plugin notification");
   ok(gTestBrowser.missingPlugins, "Test 1, Should be a missing plugin list");
   ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 1, Should know about application/x-unknown");
   ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 1, Should not know about application/x-test");
 
   var pluginNode = gTestBrowser.contentDocument.getElementById("unknown");
   ok(pluginNode, "Test 1, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED, "Test 1, plugin fallback type should be PLUGIN_UNSUPPORTED");
 
   var plugin = getTestPlugin();
   ok(plugin, "Should have a test plugin");
   plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
-  prepareTest(test2, gTestRoot + "plugin_test.html");
+  prepareTest(runAfterPluginBindingAttached(test2), gTestRoot + "plugin_test.html");
 }
 
 // Tests a page with a working plugin in it.
 function test2() {
   ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 2, Should not have displayed the missing plugin notification");
   ok(!gTestBrowser.missingPlugins, "Test 2, Should not be a missing plugin list");
 
   var plugin = getTestPlugin();
   ok(plugin, "Should have a test plugin");
   plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
-  prepareTest(test3, gTestRoot + "plugin_test.html");
+  prepareTest(runAfterPluginBindingAttached(test3), gTestRoot + "plugin_test.html");
 }
 
 // Tests a page with a disabled plugin in it.
 function test3() {
   ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 3, Should not have displayed the missing plugin notification");
   ok(!gTestBrowser.missingPlugins, "Test 3, Should not be a missing plugin list");
 
   new TabOpenListener("about:addons", test4, prepareTest5);
@@ -147,17 +163,17 @@ function test4(tab, win) {
 
 function prepareTest5() {
   info("prepareTest5");
   var plugin = getTestPlugin();
   plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
   setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml",
     function() {
       info("prepareTest5 callback");
-      prepareTest(test5, gTestRoot + "plugin_test.html");
+      prepareTest(runAfterPluginBindingAttached(test5), gTestRoot + "plugin_test.html");
   });
 }
 
 // Tests a page with a blocked plugin in it.
 function test5() {
   info("test5");
   ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 5, Should not have displayed the missing plugin notification");
   let notification = PopupNotifications.getNotification("click-to-play-plugins");
@@ -169,67 +185,67 @@ function test5() {
   ok(PopupNotifications.panel.firstChild._buttonContainer.hidden, "Part 5: The blocked plugins notification should not have any buttons visible.");
 
   ok(!gTestBrowser.missingPlugins, "Test 5, Should not be a missing plugin list");
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 5, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, "Test 5, plugin fallback type should be PLUGIN_BLOCKLISTED");
 
-  prepareTest(test6, gTestRoot + "plugin_both.html");
+  prepareTest(runAfterPluginBindingAttached(test6), gTestRoot + "plugin_both.html");
 }
 
 // Tests a page with a blocked and unknown plugin in it.
 function test6() {
   ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 6, Should have displayed the missing plugin notification");
   ok(gTestBrowser.missingPlugins, "Test 6, Should be a missing plugin list");
   ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 6, Should know about application/x-unknown");
   ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 6, application/x-test should not be a missing plugin");
 
-  prepareTest(test7, gTestRoot + "plugin_both2.html");
+  prepareTest(runAfterPluginBindingAttached(test7), gTestRoot + "plugin_both2.html");
 }
 
 // Tests a page with a blocked and unknown plugin in it (alternate order to above).
 function test7() {
   ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 7, Should have displayed the missing plugin notification");
   ok(gTestBrowser.missingPlugins, "Test 7, Should be a missing plugin list");
   ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 7, Should know about application/x-unknown");
   ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 7, application/x-test should not be a missing plugin");
 
   var plugin = getTestPlugin();
   plugin.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
   getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
 
   setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() {
-    prepareTest(test8, gTestRoot + "plugin_test.html");
+    prepareTest(runAfterPluginBindingAttached(test8), gTestRoot + "plugin_test.html");
   });
 }
 
 // Tests a page with a working plugin that is click-to-play
 function test8() {
   ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 8, Should not have displayed the missing plugin notification");
   ok(!gTestBrowser.missingPlugins, "Test 8, Should not be a missing plugin list");
   ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 8, Should have a click-to-play notification");
 
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 8, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 8, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
 
-  prepareTest(test11a, gTestRoot + "plugin_test3.html");
+  prepareTest(runAfterPluginBindingAttached(test11a), gTestRoot + "plugin_test3.html");
 }
 
 // Tests 9 & 10 removed
 
 // Tests that the going back will reshow the notification for click-to-play plugins (part 1/4)
 function test11a() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 11a, Should have a click-to-play notification");
 
-  prepareTest(test11b, "about:blank");
+  prepareTest(runAfterPluginBindingAttached(test11b), "about:blank");
 }
 
 // Tests that the going back will reshow the notification for click-to-play plugins (part 2/4)
 function test11b() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(!popupNotification, "Test 11b, Should not have a click-to-play notification");
 
   Services.obs.addObserver(test11c, "PopupNotifications-updateNotShowing", false);
@@ -243,17 +259,17 @@ function test11c() {
   waitForCondition(condition, test11d, "Test 11c, waited too long for click-to-play-plugin notification");
 }
 
 // Tests that the going back will reshow the notification for click-to-play plugins (part 4/4)
 function test11d() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 11d, Should have a click-to-play notification");
 
-  prepareTest(test12a, gHttpTestRoot + "plugin_clickToPlayAllow.html");
+  prepareTest(runAfterPluginBindingAttached(test12a), gHttpTestRoot + "plugin_clickToPlayAllow.html");
 }
 
 // Tests that the "Allow Always" permission works for click-to-play plugins
 function test12a() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 12a, Should have a click-to-play notification");
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
@@ -265,17 +281,17 @@ function test12a() {
 
   var condition = function() objLoadingContent.activated;
   waitForCondition(condition, test12b, "Test 12a, Waited too long for plugin to activate");
 }
 
 function test12b() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 12d, Should have a click-to-play notification");
-  prepareTest(test12c, gHttpTestRoot + "plugin_two_types.html");
+  prepareTest(runAfterPluginBindingAttached(test12c), gHttpTestRoot + "plugin_two_types.html");
 }
 
 // Test that the "Always" permission, when set for just the Test plugin,
 // does not also allow the Second Test plugin.
 function test12c() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 12d, Should have a click-to-play notification");
   var test = gTestBrowser.contentDocument.getElementById("test");
@@ -297,43 +313,43 @@ function test12c() {
 function test14() {
   var plugin = gTestBrowser.contentDocument.getElementById("test1");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 14, Plugin should be activated");
 
   var plugin = getTestPlugin();
   plugin.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
   getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
-  prepareTest(test15, gTestRoot + "plugin_alternate_content.html");
+  prepareTest(runAfterPluginBindingAttached(test15), gTestRoot + "plugin_alternate_content.html");
 }
 
 // Tests that the overlay is shown instead of alternate content when
 // plugins are click to play
 function test15() {
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   var doc = gTestBrowser.contentDocument;
   var mainBox = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
   ok(mainBox, "Test 15, Plugin with id=" + plugin.id + " overlay should exist");
 
-  prepareTest(test17, gTestRoot + "plugin_bug749455.html");
+  prepareTest(runAfterPluginBindingAttached(test17), gTestRoot + "plugin_bug749455.html");
 }
 
 // Test 16 removed
 
 // Tests that mContentType is used for click-to-play plugins, and not the
 // inspected type.
 function test17() {
   var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(clickToPlayNotification, "Test 17, Should have a click-to-play notification");
   var missingNotification = PopupNotifications.getNotification("missing-plugins", gTestBrowser);
   ok(!missingNotification, "Test 17, Should not have a missing plugin notification");
 
   setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
   function() {
-    prepareTest(test18a, gHttpTestRoot + "plugin_test.html");
+    prepareTest(runAfterPluginBindingAttached(test18a), gHttpTestRoot + "plugin_test.html");
   });
 }
 
 // Tests a vulnerable, updatable plugin
 function test18a() {
   var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(clickToPlayNotification, "Test 18a, Should have a click-to-play notification");
   var doc = gTestBrowser.contentDocument;
@@ -366,17 +382,17 @@ function test18b() {
   var plugin = doc.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 18b, Plugin should not be activated");
   var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
   ok(overlay.style.visibility != "hidden", "Test 18b, Plugin overlay should exist, not be hidden");
 
   setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableNoUpdate.xml",
   function() {
-    prepareTest(test18c, gHttpTestRoot + "plugin_test.html");
+    prepareTest(runAfterPluginBindingAttached(test18c), gHttpTestRoot + "plugin_test.html");
   });
 }
 
 // Tests a vulnerable plugin with no update
 function test18c() {
   var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(clickToPlayNotification, "Test 18c, Should have a click-to-play notification");
   var doc = gTestBrowser.contentDocument;
@@ -409,17 +425,17 @@ function test18d() {
 
 // continue testing "Always allow"
 function test18e() {
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 18e, Plugin should be activated");
 
   clearAllPluginPermissions();
-  prepareTest(test18f, gHttpTestRoot + "plugin_test.html");
+  prepareTest(runAfterPluginBindingAttached(test18f), gHttpTestRoot + "plugin_test.html");
 }
 
 // clicking the in-content overlay of a vulnerable plugin should bring
 // up the notification and not directly activate the plugin
 function test18f() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 18f, Should have a click-to-play notification");
   ok(notification.dismissed, "Test 18f, notification should start dismissed");
@@ -441,17 +457,17 @@ function test18g() {
   notification.options.eventCallback = null;
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 18g, Plugin should not be activated");
 
   setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml",
   function() {
     resetBlocklist();
-    prepareTest(test19a, gTestRoot + "plugin_test.html");
+    prepareTest(runAfterPluginBindingAttached(test19a), gTestRoot + "plugin_test.html");
   });
 }
 
 // Tests that clicking the icon of the overlay activates the doorhanger
 function test19a() {
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
@@ -460,17 +476,17 @@ function test19a() {
 
   var icon = doc.getAnonymousElementByAttribute(plugin, "class", "icon");
   EventUtils.synthesizeMouseAtCenter(icon, {}, gTestBrowser.contentWindow);
   let condition = function() !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
   waitForCondition(condition, test19b, "Test 19a, Waited too long for doorhanger to activate");
 }
 
 function test19b() {
-  prepareTest(test19c, gTestRoot + "plugin_test.html");
+  prepareTest(runAfterPluginBindingAttached(test19c), gTestRoot + "plugin_test.html");
 }
 
 // Tests that clicking the text of the overlay activates the plugin
 function test19c() {
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 19c, Plugin should not be activated");
@@ -479,17 +495,17 @@ function test19c() {
 
   var text = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay");
   EventUtils.synthesizeMouseAtCenter(text, {}, gTestBrowser.contentWindow);
   let condition = function() !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
   waitForCondition(condition, test19d, "Test 19c, Waited too long for doorhanger to activate");
 }
 
 function test19d() {
-  prepareTest(test19e, gTestRoot + "plugin_test.html");
+  prepareTest(runAfterPluginBindingAttached(test19e), gTestRoot + "plugin_test.html");
 }
 
 // Tests that clicking the box of the overlay activates the doorhanger
 // (just to be thorough)
 function test19e() {
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
@@ -498,17 +514,17 @@ function test19e() {
   ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, "Test 19e, Doorhanger should start out dismissed");
 
   EventUtils.synthesizeMouse(plugin, 50, 50, {}, gTestBrowser.contentWindow);
   let condition = function() !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed;
   waitForCondition(condition, test19f, "Test 19e, Waited too long for plugin to activate");
 }
 
 function test19f() {
-  prepareTest(test20a, gTestRoot + "plugin_hidden_to_visible.html");
+  prepareTest(runAfterPluginBindingAttached(test20a), gTestRoot + "plugin_hidden_to_visible.html");
 }
 
 // Tests that a plugin in a div that goes from style="display: none" to
 // "display: block" can be clicked to activate.
 function test20a() {
   var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(!clickToPlayNotification, "Test 20a, Should not have a click-to-play notification");
   var doc = gTestBrowser.contentDocument;
@@ -563,17 +579,17 @@ function test20d() {
   var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
   ok(pluginRect.width == 0, "Test 20d, plugin should have click-to-play overlay with zero width");
   ok(pluginRect.height == 0, "Test 20d, plugin should have click-to-play overlay with zero height");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 20d, plugin should be activated");
 
   clearAllPluginPermissions();
 
-  prepareTest(test21a, gTestRoot + "plugin_two_types.html");
+  prepareTest(runAfterPluginBindingAttached(test21a), gTestRoot + "plugin_two_types.html");
 }
 
 // Test having multiple different types of plugin on one page
 function test21a() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 21a, Should have a click-to-play notification");
 
   var doc = gTestBrowser.contentDocument;
@@ -691,17 +707,17 @@ function test21e() {
     ok(objLoadingContent.activated, "Test 21e, Plugin with id=" + plugin.id + " should be activated");
   }
 
   getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
   getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
 
   clearAllPluginPermissions();
 
-  prepareTest(test22, gTestRoot + "plugin_test.html");
+  prepareTest(runAfterPluginBindingAttached(test22), gTestRoot + "plugin_test.html");
 }
 
 // Tests that a click-to-play plugin retains its activated state upon reloading
 function test22() {
   ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 22, Should have a click-to-play notification");
 
   // Plugin should start as CTP
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
@@ -723,17 +739,17 @@ function test22() {
   var pluginsDiffer;
   try {
     pluginNode.checkObjectValue(oldVal);
   } catch (e) {
     pluginsDiffer = true;
   }
   ok(pluginsDiffer, "Test 22, plugin should have reloaded");
 
-  prepareTest(test23, gTestRoot + "plugin_test.html");
+  prepareTest(runAfterPluginBindingAttached(test23), gTestRoot + "plugin_test.html");
 }
 
 // Tests that a click-to-play plugin resets its activated state when changing types
 function test23() {
   ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 23, Should have a click-to-play notification");
 
   // Plugin should start as CTP
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
@@ -753,17 +769,17 @@ function test23() {
   pluginNode.parentNode.appendChild(pluginNode);
   is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, plugin should be unloaded");
   pluginNode.type = "application/x-test";
   pluginNode.parentNode.appendChild(pluginNode);
   is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, Plugin should not have activated");
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 23, Plugin should be click-to-play");
   ok(!pluginNode.activated, "Test 23, plugin node should not be activated");
 
-  prepareTest(test24a, gHttpTestRoot + "plugin_test.html");
+  prepareTest(runAfterPluginBindingAttached(test24a), gHttpTestRoot + "plugin_test.html");
 }
 
 // Test that "always allow"-ing a plugin will not allow it when it becomes
 // blocklisted.
 function test24a() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 24a, Should have a click-to-play notification");
   var plugin = gTestBrowser.contentDocument.getElementById("test");
@@ -781,17 +797,17 @@ function test24a() {
 // did the "always allow" work as intended?
 function test24b() {
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   ok(plugin, "Test 24b, Found plugin in page");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 24b, plugin should be activated");
   setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
   function() {
-    prepareTest(test24c, gHttpTestRoot + "plugin_test.html");
+    prepareTest(runAfterPluginBindingAttached(test24c), gHttpTestRoot + "plugin_test.html");
   });
 }
 
 // the plugin is now blocklisted, so it should not automatically load
 function test24c() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 24c, Should have a click-to-play notification");
   var plugin = gTestBrowser.contentDocument.getElementById("test");