diff options
Diffstat (limited to 'browser/base/content/test/plugins')
70 files changed, 5293 insertions, 0 deletions
diff --git a/browser/base/content/test/plugins/.eslintrc.js b/browser/base/content/test/plugins/.eslintrc.js new file mode 100644 index 000000000..7c8021192 --- /dev/null +++ b/browser/base/content/test/plugins/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + "extends": [ + "../../../../../testing/mochitest/browser.eslintrc.js" + ] +}; diff --git a/browser/base/content/test/plugins/blockNoPlugins.xml b/browser/base/content/test/plugins/blockNoPlugins.xml new file mode 100644 index 000000000..e4e191b37 --- /dev/null +++ b/browser/base/content/test/plugins/blockNoPlugins.xml @@ -0,0 +1,7 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310001"> + <emItems> + </emItems> + <pluginItems> + </pluginItems> +</blocklist> diff --git a/browser/base/content/test/plugins/blockPluginHard.xml b/browser/base/content/test/plugins/blockPluginHard.xml new file mode 100644 index 000000000..24eb5bc6f --- /dev/null +++ b/browser/base/content/test/plugins/blockPluginHard.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000"> + <emItems> + </emItems> + <pluginItems> + <pluginItem blockID="p9999"> + <match name="filename" exp="libnptest\.so|nptest\.dll|Test\.plugin" /> + <versionRange severity="2"></versionRange> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/browser/base/content/test/plugins/blockPluginInfoURL.xml b/browser/base/content/test/plugins/blockPluginInfoURL.xml new file mode 100644 index 000000000..c16808896 --- /dev/null +++ b/browser/base/content/test/plugins/blockPluginInfoURL.xml @@ -0,0 +1,12 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000"> + <emItems> + </emItems> + <pluginItems> + <pluginItem blockID="p9999"> + <match name="filename" exp="libnptest\.so|nptest\.dll|Test\.plugin" /> + <versionRange severity="2"></versionRange> + <infoURL>http://test.url.com/</infoURL> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/browser/base/content/test/plugins/blockPluginVulnerableNoUpdate.xml b/browser/base/content/test/plugins/blockPluginVulnerableNoUpdate.xml new file mode 100644 index 000000000..bf8545afe --- /dev/null +++ b/browser/base/content/test/plugins/blockPluginVulnerableNoUpdate.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000"> + <emItems> + </emItems> + <pluginItems> + <pluginItem blockID="p9999"> + <match name="filename" exp="libnptest\.so|nptest\.dll|Test\.plugin" /> + <versionRange severity="0" vulnerabilitystatus="2"></versionRange> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/browser/base/content/test/plugins/blockPluginVulnerableUpdatable.xml b/browser/base/content/test/plugins/blockPluginVulnerableUpdatable.xml new file mode 100644 index 000000000..5545162b1 --- /dev/null +++ b/browser/base/content/test/plugins/blockPluginVulnerableUpdatable.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000"> + <emItems> + </emItems> + <pluginItems> + <pluginItem blockID="p9999"> + <match name="filename" exp="libnptest\.so|nptest\.dll|Test\.plugin" /> + <versionRange severity="0" vulnerabilitystatus="1"></versionRange> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/browser/base/content/test/plugins/blocklist_proxy.js b/browser/base/content/test/plugins/blocklist_proxy.js new file mode 100644 index 000000000..1a4ed4726 --- /dev/null +++ b/browser/base/content/test/plugins/blocklist_proxy.js @@ -0,0 +1,78 @@ +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cu = Components.utils; +var Cm = Components.manager; + +const kBlocklistServiceUUID = "{66354bc9-7ed1-4692-ae1d-8da97d6b205e}"; +const kBlocklistServiceContractID = "@mozilla.org/extensions/blocklist;1"; +const kBlocklistServiceFactory = Cm.getClassObject(Cc[kBlocklistServiceContractID], Ci.nsIFactory); + +Cu.import('resource://gre/modules/XPCOMUtils.jsm'); + +/* + * A lightweight blocklist proxy for the testing purposes. + */ +var BlocklistProxy = { + _uuid: null, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsIBlocklistService, + Ci.nsITimerCallback]), + + init: function() { + if (!this._uuid) { + this._uuid = + Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator) + .generateUUID(); + Cm.nsIComponentRegistrar.registerFactory(this._uuid, "", + "@mozilla.org/extensions/blocklist;1", + this); + } + }, + + uninit: function() { + if (this._uuid) { + Cm.nsIComponentRegistrar.unregisterFactory(this._uuid, this); + Cm.nsIComponentRegistrar.registerFactory(Components.ID(kBlocklistServiceUUID), + "Blocklist Service", + "@mozilla.org/extensions/blocklist;1", + kBlocklistServiceFactory); + this._uuid = null; + } + }, + + notify: function (aTimer) { + }, + + observe: function (aSubject, aTopic, aData) { + }, + + isAddonBlocklisted: function (aAddon, aAppVersion, aToolkitVersion) { + return false; + }, + + getAddonBlocklistState: function (aAddon, aAppVersion, aToolkitVersion) { + return 0; // STATE_NOT_BLOCKED + }, + + getPluginBlocklistState: function (aPluginTag, aAppVersion, aToolkitVersion) { + return 0; // STATE_NOT_BLOCKED + }, + + getAddonBlocklistURL: function (aAddon, aAppVersion, aToolkitVersion) { + return ""; + }, + + getPluginBlocklistURL: function (aPluginTag) { + return ""; + }, + + getPluginInfoURL: function (aPluginTag) { + return ""; + }, +} + +BlocklistProxy.init(); +addEventListener("unload", () => { + BlocklistProxy.uninit(); +}); diff --git a/browser/base/content/test/plugins/browser.ini b/browser/base/content/test/plugins/browser.ini new file mode 100644 index 000000000..cfc1f769c --- /dev/null +++ b/browser/base/content/test/plugins/browser.ini @@ -0,0 +1,78 @@ +[DEFAULT] +support-files = + blocklist_proxy.js + blockNoPlugins.xml + blockPluginHard.xml + blockPluginInfoURL.xml + blockPluginVulnerableNoUpdate.xml + blockPluginVulnerableUpdatable.xml + browser_clearplugindata.html + browser_clearplugindata_noage.html + head.js + plugin_add_dynamically.html + plugin_alternate_content.html + plugin_big.html + plugin_both.html + plugin_both2.html + plugin_bug744745.html + plugin_bug749455.html + plugin_bug787619.html + plugin_bug797677.html + plugin_bug820497.html + plugin_clickToPlayAllow.html + plugin_clickToPlayDeny.html + plugin_data_url.html + plugin_hidden_to_visible.html + plugin_iframe.html + plugin_outsideScrollArea.html + plugin_overlayed.html + plugin_positioned.html + plugin_small.html + plugin_small_2.html + plugin_syncRemoved.html + plugin_test.html + plugin_test2.html + plugin_test3.html + plugin_two_types.html + plugin_unknown.html + plugin_crashCommentAndURL.html + plugin_zoom.html + +[browser_bug743421.js] +[browser_bug744745.js] +[browser_bug787619.js] +[browser_bug797677.js] +[browser_bug812562.js] +[browser_bug818118.js] +[browser_bug820497.js] +[browser_clearplugindata.js] +[browser_CTP_context_menu.js] +skip-if = toolkit == "gtk2" || toolkit == "gtk3" # fails intermittently on Linux (bug 909342) +[browser_CTP_crashreporting.js] +skip-if = !crashreporter +[browser_CTP_data_urls.js] +[browser_CTP_drag_drop.js] +[browser_CTP_hide_overlay.js] +[browser_CTP_iframe.js] +[browser_CTP_multi_allow.js] +[browser_CTP_nonplugins.js] +[browser_CTP_notificationBar.js] +[browser_CTP_outsideScrollArea.js] +[browser_CTP_remove_navigate.js] +[browser_CTP_resize.js] +[browser_CTP_zoom.js] +[browser_blocking.js] +[browser_plugins_added_dynamically.js] +[browser_pluginnotification.js] +[browser_plugin_reloading.js] +[browser_blocklist_content.js] +skip-if = !e10s +[browser_globalplugin_crashinfobar.js] +skip-if = !crashreporter +[browser_pluginCrashCommentAndURL.js] +skip-if = !crashreporter +[browser_pageInfo_plugins.js] +[browser_pluginCrashReportNonDeterminism.js] +skip-if = !crashreporter || os == 'linux' # Bug 1152811 +[browser_private_clicktoplay.js] + diff --git a/browser/base/content/test/plugins/browser_CTP_context_menu.js b/browser/base/content/test/plugins/browser_CTP_context_menu.js new file mode 100644 index 000000000..03f3e18ef --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_context_menu.js @@ -0,0 +1,69 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + }); +}); + +// Test that the activate action in content menus for CTP plugins works +add_task(function* () { + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + gBrowser.selectedTab = gBrowser.addTab(); + + Services.prefs.setBoolPref("plugins.click_to_play", true); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + let bindingPromise = waitForEvent(gBrowser.selectedBrowser, "PluginBindingAttached", null, true, true); + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + yield bindingPromise; + + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser); + ok(popupNotification, "Test 1, Should have a click-to-play notification"); + + // check plugin state + let pluginInfo = yield promiseForPluginInfo("test", gBrowser.selectedBrowser); + ok(!pluginInfo.activated, "plugin should not be activated"); + + // Display a context menu on the test plugin so we can test + // activation menu options. + yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + let bounds = plugin.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("contextmenu", left, top, 2, 1, 0); + }); + + popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser); + ok(popupNotification, "Should have a click-to-play notification"); + ok(popupNotification.dismissed, "notification should be dismissed"); + + // fixes a occasional test timeout on win7 opt + yield promiseForCondition(() => document.getElementById("context-ctp-play")); + + let actMenuItem = document.getElementById("context-ctp-play"); + ok(actMenuItem, "Should have a context menu entry for activating the plugin"); + + // Activate the plugin via the context menu + EventUtils.synthesizeMouseAtCenter(actMenuItem, {}); + + yield promiseForCondition(() => !PopupNotifications.panel.dismissed && PopupNotifications.panel.firstChild); + + // Activate the plugin + PopupNotifications.panel.firstChild._primaryButton.click(); + + // check plugin state + pluginInfo = yield promiseForPluginInfo("test", gBrowser.selectedBrowser); + ok(pluginInfo.activated, "plugin should not be activated"); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_crashreporting.js b/browser/base/content/test/plugins/browser_CTP_crashreporting.js new file mode 100644 index 000000000..bb52d5704 --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_crashreporting.js @@ -0,0 +1,233 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs"; +const PLUGIN_PAGE = gTestRoot + "plugin_big.html"; +const PLUGIN_SMALL_PAGE = gTestRoot + "plugin_small.html"; + +/** + * Takes an nsIPropertyBag and converts it into a JavaScript Object. It + * will also convert any nsIPropertyBag's within the nsIPropertyBag + * recursively. + * + * @param aBag + * The nsIPropertyBag to convert. + * @return Object + * Keyed on the names of the nsIProperty's within the nsIPropertyBag, + * and mapping to their values. + */ +function convertPropertyBag(aBag) { + let result = {}; + let enumerator = aBag.enumerator; + while (enumerator.hasMoreElements()) { + let { name, value } = enumerator.getNext().QueryInterface(Ci.nsIProperty); + if (value instanceof Ci.nsIPropertyBag) { + value = convertPropertyBag(value); + } + result[name] = value; + } + return result; +} + +add_task(function* setup() { + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + // The test harness sets MOZ_CRASHREPORTER_NO_REPORT, which disables plugin + // crash reports. This test needs them enabled. The test also needs a mock + // report server, and fortunately one is already set up by toolkit/ + // crashreporter/test/Makefile.in. Assign its URL to MOZ_CRASHREPORTER_URL, + // which CrashSubmit.jsm uses as a server override. + let env = Cc["@mozilla.org/process/environment;1"]. + getService(Components.interfaces.nsIEnvironment); + let noReport = env.get("MOZ_CRASHREPORTER_NO_REPORT"); + let serverURL = env.get("MOZ_CRASHREPORTER_URL"); + env.set("MOZ_CRASHREPORTER_NO_REPORT", ""); + env.set("MOZ_CRASHREPORTER_URL", SERVER_URL); + + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + registerCleanupFunction(function cleanUp() { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport); + env.set("MOZ_CRASHREPORTER_URL", serverURL); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + window.focus(); + }); +}); + +/** + * Test that plugin crash submissions still work properly after + * click-to-play activation. + */ +add_task(function*() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: PLUGIN_PAGE, + }, function* (browser) { + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(browser); + + let pluginInfo = yield promiseForPluginInfo("test", browser); + ok(!pluginInfo.activated, "Plugin should not be activated"); + + // Simulate clicking the "Allow Always" button. + let notification = PopupNotifications.getNotification("click-to-play-plugins", browser); + yield promiseForNotificationShown(notification, browser); + PopupNotifications.panel.firstChild._primaryButton.click(); + + // Prepare a crash report topic observer that only returns when + // the crash report has been successfully sent. + let crashReportChecker = (subject, data) => { + return (data == "success"); + }; + let crashReportPromise = TestUtils.topicObserved("crash-report-status", + crashReportChecker); + + yield ContentTask.spawn(browser, null, function*() { + let plugin = content.document.getElementById("test"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + + yield ContentTaskUtils.waitForCondition(() => { + return plugin.activated; + }, "Waited too long for plugin to activate."); + + try { + Components.utils.waiveXrays(plugin).crash(); + } catch (e) { + } + + let doc = plugin.ownerDocument; + + let getUI = (anonid) => { + return doc.getAnonymousElementByAttribute(plugin, "anonid", anonid); + }; + + // Now wait until the plugin crash report UI shows itself, which is + // asynchronous. + let statusDiv; + + yield ContentTaskUtils.waitForCondition(() => { + statusDiv = getUI("submitStatus"); + return statusDiv.getAttribute("status") == "please"; + }, "Waited too long for plugin to show crash report UI"); + + // Make sure the UI matches our expectations... + let style = content.getComputedStyle(getUI("pleaseSubmit")); + if (style.display != "block") { + throw new Error(`Submission UI visibility is not correct. ` + + `Expected block style, got ${style.display}.`); + } + + // Fill the crash report in with some test values that we'll test for in + // the parent. + getUI("submitComment").value = "a test comment"; + let optIn = getUI("submitURLOptIn"); + if (!optIn.checked) { + throw new Error("URL opt-in should default to true."); + } + + // Submit the report. + optIn.click(); + getUI("submitButton").click(); + + // And wait for the parent to say that the crash report was submitted + // successfully. + yield ContentTaskUtils.waitForCondition(() => { + return statusDiv.getAttribute("status") == "success"; + }, "Timed out waiting for plugin binding to be in success state"); + }); + + let [subject, ] = yield crashReportPromise; + + ok(subject instanceof Ci.nsIPropertyBag, + "The crash report subject should be an nsIPropertyBag."); + + let crashData = convertPropertyBag(subject); + ok(crashData.serverCrashID, "Should have a serverCrashID set."); + + // Remove the submitted report file after ensuring it exists. + let file = Cc["@mozilla.org/file/local;1"] + .createInstance(Ci.nsILocalFile); + file.initWithPath(Services.crashmanager._submittedDumpsDir); + file.append(crashData.serverCrashID + ".txt"); + ok(file.exists(), "Submitted report file should exist"); + file.remove(false); + + ok(crashData.extra, "Extra data should exist"); + is(crashData.extra.PluginUserComment, "a test comment", + "Comment in extra data should match comment in textbox"); + + is(crashData.extra.PluginContentURL, undefined, + "URL should be absent from extra data when opt-in not checked"); + }); +}); + +/** + * Test that plugin crash submissions still work properly after + * click-to-play with the notification bar. + */ +add_task(function*() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: PLUGIN_SMALL_PAGE, + }, function* (browser) { + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(browser); + + let pluginInfo = yield promiseForPluginInfo("test", browser); + ok(pluginInfo.activated, "Plugin should be activated from previous test"); + + // Prepare a crash report topic observer that only returns when + // the crash report has been successfully sent. + let crashReportChecker = (subject, data) => { + return (data == "success"); + }; + let crashReportPromise = TestUtils.topicObserved("crash-report-status", + crashReportChecker); + + yield ContentTask.spawn(browser, null, function*() { + let plugin = content.document.getElementById("test"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + + yield ContentTaskUtils.waitForCondition(() => { + return plugin.activated; + }, "Waited too long for plugin to activate."); + + try { + Components.utils.waiveXrays(plugin).crash(); + } catch (e) {} + }); + + // Wait for the notification bar to be displayed. + let notification = yield waitForNotificationBar("plugin-crashed", browser); + + // Then click the button to submit the crash report. + let buttons = notification.querySelectorAll(".notification-button"); + is(buttons.length, 2, "Should have two buttons."); + + // The "Submit Crash Report" button should be the second one. + let submitButton = buttons[1]; + submitButton.click(); + + let [subject, ] = yield crashReportPromise; + + ok(subject instanceof Ci.nsIPropertyBag, + "The crash report subject should be an nsIPropertyBag."); + + let crashData = convertPropertyBag(subject); + ok(crashData.serverCrashID, "Should have a serverCrashID set."); + + // Remove the submitted report file after ensuring it exists. + let file = Cc["@mozilla.org/file/local;1"] + .createInstance(Ci.nsILocalFile); + file.initWithPath(Services.crashmanager._submittedDumpsDir); + file.append(crashData.serverCrashID + ".txt"); + ok(file.exists(), "Submitted report file should exist"); + file.remove(false); + + is(crashData.extra.PluginContentURL, undefined, + "URL should be absent from extra data when opt-in not checked"); + }); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_data_urls.js b/browser/base/content/test/plugins/browser_CTP_data_urls.js new file mode 100644 index 000000000..0f4747b1e --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_data_urls.js @@ -0,0 +1,255 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); +var gTestBrowser = null; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in"); +}); + +// Test that the click-to-play doorhanger still works when navigating to data URLs +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_data_url.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "Test 1a, Should have a click-to-play notification"); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 1a, plugin should not be activated"); + + let loadPromise = promiseTabLoadEvent(gBrowser.selectedTab); + yield ContentTask.spawn(gTestBrowser, {}, function* () { + // navigate forward to a page with 'test' in it + content.document.getElementById("data-link-1").click(); + }); + yield loadPromise; + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "Test 1b, Should have a click-to-play notification"); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 1b, plugin should not be activated"); + + let promise = promisePopupNotification("click-to-play-plugins"); + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + let bounds = plugin.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + yield promise; + + // Simulate clicking the "Allow Always" button. + let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed && + PopupNotifications.panel.firstChild; + yield promiseForCondition(condition); + PopupNotifications.panel.firstChild._primaryButton.click(); + + // check plugin state + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 1b, plugin should be activated"); +}); + +// Test that the click-to-play notification doesn't break when navigating +// to data URLs with multiple plugins. +add_task(function* () { + // We click activated above + clearAllPluginPermissions(); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_data_url.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 2a, Should have a click-to-play notification"); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 2a, plugin should not be activated"); + + let loadPromise = promiseTabLoadEvent(gBrowser.selectedTab); + yield ContentTask.spawn(gTestBrowser, {}, function* () { + // navigate forward to a page with 'test1' & 'test2' in it + content.document.getElementById("data-link-2").click(); + }); + yield loadPromise; + + // Work around for delayed PluginBindingAttached + yield ContentTask.spawn(gTestBrowser, {}, function* () { + content.document.getElementById("test1").clientTop; + content.document.getElementById("test2").clientTop; + }); + + pluginInfo = yield promiseForPluginInfo("test1"); + ok(!pluginInfo.activated, "Test 2a, test1 should not be activated"); + pluginInfo = yield promiseForPluginInfo("test2"); + ok(!pluginInfo.activated, "Test 2a, test2 should not be activated"); + + notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 2b, Should have a click-to-play notification"); + + yield promiseForNotificationShown(notification); + + // Simulate choosing "Allow now" for the test plugin + is(notification.options.pluginData.size, 2, "Test 2b, Should have two types of plugin in the notification"); + + let centerAction = null; + for (let action of notification.options.pluginData.values()) { + if (action.pluginName == "Test") { + centerAction = action; + break; + } + } + ok(centerAction, "Test 2b, found center action for the Test plugin"); + + let centerItem = null; + for (let item of PopupNotifications.panel.firstChild.childNodes) { + is(item.value, "block", "Test 2b, all plugins should start out blocked"); + if (item.action == centerAction) { + centerItem = item; + break; + } + } + ok(centerItem, "Test 2b, found center item for the Test plugin"); + + // "click" the button to activate the Test plugin + centerItem.value = "allownow"; + PopupNotifications.panel.firstChild._primaryButton.click(); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + // check plugin state + pluginInfo = yield promiseForPluginInfo("test1"); + ok(pluginInfo.activated, "Test 2b, plugin should be activated"); +}); + +add_task(function* () { + // We click activated above + clearAllPluginPermissions(); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_data_url.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); +}); + +// Test that when navigating to a data url, the plugin permission is inherited +add_task(function* () { + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 3a, Should have a click-to-play notification"); + + // check plugin state + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 3a, plugin should not be activated"); + + let promise = promisePopupNotification("click-to-play-plugins"); + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + let bounds = plugin.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + yield promise; + + // Simulate clicking the "Allow Always" button. + let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed && + PopupNotifications.panel.firstChild; + yield promiseForCondition(condition); + PopupNotifications.panel.firstChild._primaryButton.click(); + + // check plugin state + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 3a, plugin should be activated"); + + let loadPromise = promiseTabLoadEvent(gBrowser.selectedTab); + yield ContentTask.spawn(gTestBrowser, {}, function* () { + // navigate forward to a page with 'test' in it + content.document.getElementById("data-link-1").click(); + }); + yield loadPromise; + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + // check plugin state + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 3b, plugin should be activated"); + + clearAllPluginPermissions(); +}); + +// Test that the click-to-play doorhanger still works +// when directly navigating to data URLs. +// Fails, bug XXX. Plugins plus a data url don't fire a load event. +/* +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, + "data:text/html,Hi!<embed id='test' style='width:200px; height:200px' type='application/x-test'/>"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 4a, Should have a click-to-play notification"); + + // check plugin state + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 4a, plugin should not be activated"); + + let promise = promisePopupNotification("click-to-play-plugins"); + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + let bounds = plugin.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + yield promise; + + // Simulate clicking the "Allow Always" button. + let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed && + PopupNotifications.panel.firstChild; + yield promiseForCondition(condition); + PopupNotifications.panel.firstChild._primaryButton.click(); + + // check plugin state + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 4a, plugin should be activated"); +}); +*/ diff --git a/browser/base/content/test/plugins/browser_CTP_drag_drop.js b/browser/base/content/test/plugins/browser_CTP_drag_drop.js new file mode 100644 index 000000000..7c9858e27 --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_drag_drop.js @@ -0,0 +1,96 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gNewWindow = null; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gNewWindow.close(); + gNewWindow = null; + window.focus(); + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + gBrowser.selectedTab = gBrowser.addTab(); + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + + yield promisePopupNotification("click-to-play-plugins"); +}); + +add_task(function* () { + gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab); + + // XXX technically can't load fire before we get this call??? + yield waitForEvent(gNewWindow, "load", null, true); + + yield promisePopupNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser); + + ok(PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser), "Should have a click-to-play notification in the tab in the new window"); + ok(!PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser), "Should not have a click-to-play notification in the old window now"); +}); + +add_task(function* () { + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, gNewWindow.gBrowser.selectedTab); + + yield promisePopupNotification("click-to-play-plugins", gBrowser.selectedBrowser); + + ok(PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser), "Should have a click-to-play notification in the initial tab again"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); +}); + +add_task(function* () { + yield promisePopupNotification("click-to-play-plugins"); + + gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab); + + yield promiseWaitForFocus(gNewWindow); + + yield promisePopupNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser); +}); + +add_task(function* () { + ok(PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser), "Should have a click-to-play notification in the tab in the new window"); + ok(!PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser), "Should not have a click-to-play notification in the old window now"); + + let pluginInfo = yield promiseForPluginInfo("test", gNewWindow.gBrowser.selectedBrowser); + ok(!pluginInfo.activated, "plugin should not be activated"); + + yield ContentTask.spawn(gNewWindow.gBrowser.selectedBrowser, {}, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let bounds = plugin.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + + let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser).dismissed && gNewWindow.PopupNotifications.panel.firstChild; + yield promiseForCondition(condition); +}); + +add_task(function* () { + // Click the activate button on doorhanger to make sure it works + gNewWindow.PopupNotifications.panel.firstChild._primaryButton.click(); + + let pluginInfo = yield promiseForPluginInfo("test", gNewWindow.gBrowser.selectedBrowser); + ok(pluginInfo.activated, "plugin should be activated"); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_hide_overlay.js b/browser/base/content/test/plugins/browser_CTP_hide_overlay.js new file mode 100644 index 000000000..5fab7f6ed --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_hide_overlay.js @@ -0,0 +1,88 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + gBrowser.selectedTab = gBrowser.addTab(); + + Services.prefs.setBoolPref("plugins.click_to_play", true); + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + + // Tests that the overlay can be hidden for plugins using the close icon. + yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon") + let bounds = closeIcon.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + + Assert.ok(!overlay.classList.contains("visible"), "overlay should be hidden."); + }); +}); + +// Test that the overlay cannot be interacted with after the user closes the overlay +add_task(function* () { + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + + yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon") + let closeIconBounds = closeIcon.getBoundingClientRect(); + let overlayBounds = overlay.getBoundingClientRect(); + let overlayLeft = (overlayBounds.left + overlayBounds.right) / 2; + let overlayTop = (overlayBounds.left + overlayBounds.right) / 2 ; + let closeIconLeft = (closeIconBounds.left + closeIconBounds.right) / 2; + let closeIconTop = (closeIconBounds.top + closeIconBounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + // Simulate clicking on the close icon. + utils.sendMouseEvent("mousedown", closeIconLeft, closeIconTop, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", closeIconLeft, closeIconTop, 0, 1, 0, false, 0, 0); + + // Simulate clicking on the overlay. + utils.sendMouseEvent("mousedown", overlayLeft, overlayTop, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", overlayLeft, overlayTop, 0, 1, 0, false, 0, 0); + + Assert.ok(overlay.hasAttribute("dismissed") && !overlay.classList.contains("visible"), + "Overlay should be hidden"); + }); + + let notification = PopupNotifications.getNotification("click-to-play-plugins"); + + ok(notification.dismissed, "No notification should be shown"); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_iframe.js b/browser/base/content/test/plugins/browser_CTP_iframe.js new file mode 100644 index 000000000..58565559f --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_iframe.js @@ -0,0 +1,48 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + gBrowser.selectedTab = gBrowser.addTab(); + + Services.prefs.setBoolPref("plugins.click_to_play", true); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_iframe.html"); + + // Tests that the overlays are visible and actionable if the plugin is in an iframe. + + yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () { + let frame = content.document.getElementById("frame"); + let doc = frame.contentDocument; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(plugin && overlay.classList.contains("visible"), + "Test 1, Plugin overlay should exist, not be hidden"); + + let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon"); + let bounds = closeIcon.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = doc.defaultView.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + Assert.ok(!overlay.classList.contains("visible"), + "Test 1, Plugin overlay should exist, be hidden"); + }); +}); + diff --git a/browser/base/content/test/plugins/browser_CTP_multi_allow.js b/browser/base/content/test/plugins/browser_CTP_multi_allow.js new file mode 100644 index 000000000..7bc6aaabf --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_multi_allow.js @@ -0,0 +1,99 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + gBrowser.selectedTab = gBrowser.addTab(); + + Services.prefs.setBoolPref("plugins.click_to_play", true); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_two_types.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + + // Test that the click-to-play doorhanger for multiple plugins shows the correct + // state when re-opening without reloads or navigation. + + let pluginInfo = yield promiseForPluginInfo("test", gBrowser.selectedBrowser); + ok(!pluginInfo.activated, "plugin should be activated"); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser); + ok(notification, "Test 1a, Should have a click-to-play notification"); + + yield promiseForNotificationShown(notification); + + is(notification.options.pluginData.size, 2, + "Test 1a, Should have two types of plugin in the notification"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + + is(PopupNotifications.panel.firstChild.childNodes.length, 2, "have child nodes"); + + let pluginItem = null; + for (let item of PopupNotifications.panel.firstChild.childNodes) { + is(item.value, "block", "Test 1a, all plugins should start out blocked"); + if (item.action.pluginName == "Test") { + pluginItem = item; + } + } + + // Choose "Allow now" for the test plugin + pluginItem.value = "allownow"; + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test", gBrowser.selectedBrowser); + ok(pluginInfo.activated, "plugin should be activated"); + + notification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser); + ok(notification, "Test 1b, Should have a click-to-play notification"); + + yield promiseForNotificationShown(notification); + + pluginItem = null; + for (let item of PopupNotifications.panel.firstChild.childNodes) { + if (item.action.pluginName == "Test") { + is(item.value, "allownow", "Test 1b, Test plugin should now be set to 'Allow now'"); + } else { + is(item.value, "block", "Test 1b, Second Test plugin should still be blocked"); + pluginItem = item; + } + } + + // Choose "Allow and remember" for the Second Test plugin + pluginItem.value = "allowalways"; + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("secondtestA", gBrowser.selectedBrowser); + ok(pluginInfo.activated, "plugin should be activated"); + + notification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser); + ok(notification, "Test 1c, Should have a click-to-play notification"); + + yield promiseForNotificationShown(notification); + + for (let item of PopupNotifications.panel.firstChild.childNodes) { + if (item.action.pluginName == "Test") { + is(item.value, "allownow", "Test 1c, Test plugin should be set to 'Allow now'"); + } else { + is(item.value, "allowalways", "Test 1c, Second Test plugin should be set to 'Allow always'"); + } + } +}); diff --git a/browser/base/content/test/plugins/browser_CTP_nonplugins.js b/browser/base/content/test/plugins/browser_CTP_nonplugins.js new file mode 100644 index 000000000..cdef44d9d --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_nonplugins.js @@ -0,0 +1,58 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + gBrowser.selectedTab = gBrowser.addTab(); + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_DISABLED, "Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_two_types.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + + // Test that the click-to-play notification is not shown for non-plugin object elements + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser); + ok(popupNotification, "Test 1, Should have a click-to-play notification"); + + let pluginRemovedPromise = waitForEvent(gBrowser.selectedBrowser, "PluginRemoved", null, true, true); + yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () { + let plugin = content.document.getElementById("secondtestA"); + plugin.parentNode.removeChild(plugin); + plugin = content.document.getElementById("secondtestB"); + plugin.parentNode.removeChild(plugin); + + let image = content.document.createElement("object"); + image.type = "image/png"; + image.data = "moz.png"; + content.document.body.appendChild(image); + }); + yield pluginRemovedPromise; + + popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser); + ok(popupNotification, "Test 2, Should have a click-to-play notification"); + + yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + plugin.parentNode.removeChild(plugin); + }); + + popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser); + ok(popupNotification, "Test 3, Should still have a click-to-play notification"); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_notificationBar.js b/browser/base/content/test/plugins/browser_CTP_notificationBar.js new file mode 100644 index 000000000..3c7bd911c --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_notificationBar.js @@ -0,0 +1,151 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); + + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + let newTab = gBrowser.addTab(); + gBrowser.selectedTab = newTab; + gTestBrowser = gBrowser.selectedBrowser; +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_small.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + // Expecting a notification bar for hidden plugins + yield promiseForNotificationBar("plugin-hidden", gTestBrowser); +}); + +add_task(function* () { + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_small.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notificationBox = gBrowser.getNotificationBox(gTestBrowser); + yield promiseForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null); +}); + +add_task(function* () { + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_overlayed.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + // Expecting a plugin notification bar when plugins are overlaid. + yield promiseForNotificationBar("plugin-hidden", gTestBrowser); +}); + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_overlayed.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.equal(plugin.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, + "Test 3b, plugin fallback type should be PLUGIN_CLICK_TO_PLAY"); + }); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 1a, plugin should not be activated"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(!(overlay && overlay.classList.contains("visible")), + "Test 3b, overlay should be hidden."); + }); +}); + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_positioned.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + // Expecting a plugin notification bar when plugins are overlaid offscreen. + yield promisePopupNotification("click-to-play-plugins"); + yield promiseForNotificationBar("plugin-hidden", gTestBrowser); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.equal(plugin.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, + "Test 4b, plugin fallback type should be PLUGIN_CLICK_TO_PLAY"); + }); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(!(overlay && overlay.classList.contains("visible")), + "Test 4b, overlay should be hidden."); + }); +}); + +// Test that the notification bar is getting dismissed when directly activating plugins +// via the doorhanger. + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_small.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + // Expecting a plugin notification bar when plugins are overlaid offscreen. + yield promisePopupNotification("click-to-play-plugins"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.equal(plugin.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, + "Test 6, Plugin should be click-to-play"); + }); + + yield promisePopupNotification("click-to-play-plugins"); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 6, Should have a click-to-play notification"); + + // simulate "always allow" + yield promiseForNotificationShown(notification); + + PopupNotifications.panel.firstChild._primaryButton.click(); + + let notificationBox = gBrowser.getNotificationBox(gTestBrowser); + yield promiseForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 7, plugin should be activated"); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_outsideScrollArea.js b/browser/base/content/test/plugins/browser_CTP_outsideScrollArea.js new file mode 100644 index 000000000..ccb4d11d7 --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_outsideScrollArea.js @@ -0,0 +1,120 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + let newTab = gBrowser.addTab(); + gBrowser.selectedTab = newTab; + gTestBrowser = gBrowser.selectedBrowser; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!popupNotification, "Test 1, Should not have a click-to-play notification"); +}); + +// Test that the click-to-play overlay is not hidden for elements +// partially or fully outside the viewport. + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_outsideScrollArea.html"); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let doc = content.document; + let p = doc.createElement('embed'); + + p.setAttribute('id', 'test'); + p.setAttribute('type', 'application/x-test'); + p.style.left = "0"; + p.style.bottom = "200px"; + + doc.getElementById('container').appendChild(p); + }); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + let doc = content.document; + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(overlay && overlay.classList.contains("visible"), + "Test 2, overlay should be visible."); + }); +}); + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_outsideScrollArea.html"); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let doc = content.document; + let p = doc.createElement('embed'); + + p.setAttribute('id', 'test'); + p.setAttribute('type', 'application/x-test'); + p.style.left = "0"; + p.style.bottom = "-410px"; + + doc.getElementById('container').appendChild(p); + }); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let plugin = content.document.getElementById("test"); + let doc = content.document; + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(overlay && overlay.classList.contains("visible"), + "Test 3, overlay should be visible."); + }); +}); + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_outsideScrollArea.html"); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let doc = content.document; + let p = doc.createElement('embed'); + + p.setAttribute('id', 'test'); + p.setAttribute('type', 'application/x-test'); + p.style.left = "-600px"; + p.style.bottom = "0"; + + doc.getElementById('container').appendChild(p); + }); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + yield ContentTask.spawn(gTestBrowser, null, function* () { + let plugin = content.document.getElementById("test"); + let doc = content.document; + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(!(overlay && overlay.classList.contains("visible")), + "Test 4, overlay should be hidden."); + }); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_remove_navigate.js b/browser/base/content/test/plugins/browser_CTP_remove_navigate.js new file mode 100644 index 000000000..8ee1c5b5a --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_remove_navigate.js @@ -0,0 +1,79 @@ +const gTestRoot = getRootDirectory(gTestPath); +const gHttpTestRoot = gTestRoot.replace("chrome://mochitests/content/", + "http://127.0.0.1:8888/"); + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + }); + + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in"); +}); + +/** + * Tests that if a plugin is removed just as we transition to + * a different page, that we don't show the hidden plugin + * notification bar on the new page. + */ +add_task(function* () { + gBrowser.selectedTab = gBrowser.addTab(); + + // Load up a page with a plugin... + let notificationPromise = waitForNotificationBar("plugin-hidden", gBrowser.selectedBrowser); + yield promiseTabLoadEvent(gBrowser.selectedTab, gHttpTestRoot + "plugin_small.html"); + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + yield notificationPromise; + + // Trigger the PluginRemoved event to be fired, and then immediately + // browse to a new page. + yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + plugin.remove(); + }); + + yield promiseTabLoadEvent(gBrowser.selectedTab, "about:mozilla"); + + // There should be no hidden plugin notification bar at about:mozilla. + let notificationBox = gBrowser.getNotificationBox(gBrowser.selectedBrowser); + is(notificationBox.getNotificationWithValue("plugin-hidden"), null, + "Expected no notification box"); +}); + +/** + * Tests that if a plugin is removed just as we transition to + * a different page with a plugin, that we show the right notification + * for the new page. + */ +add_task(function* () { + // Load up a page with a plugin... + let notificationPromise = waitForNotificationBar("plugin-hidden", gBrowser.selectedBrowser); + yield promiseTabLoadEvent(gBrowser.selectedTab, gHttpTestRoot + "plugin_small.html"); + yield promiseUpdatePluginBindings(gBrowser.selectedBrowser); + yield notificationPromise; + + // Trigger the PluginRemoved event to be fired, and then immediately + // browse to a new page. + yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + plugin.remove(); + }); +}); + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gHttpTestRoot + "plugin_small_2.html"); + let notification = yield waitForNotificationBar("plugin-hidden", gBrowser.selectedBrowser); + ok(notification, "There should be a notification shown for the new page."); + // Ensure that the notification is showing information about + // the x-second-test plugin. + let label = notification.label; + ok(label.includes("Second Test"), "Should mention the second plugin"); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_resize.js b/browser/base/content/test/plugins/browser_CTP_resize.js new file mode 100644 index 000000000..9b2a2cd82 --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_resize.js @@ -0,0 +1,130 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + let newTab = gBrowser.addTab(); + gBrowser.selectedTab = newTab; + gTestBrowser = gBrowser.selectedBrowser; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!popupNotification, "Test 1, Should not have a click-to-play notification"); + + yield promiseTabLoadEvent(newTab, gTestRoot + "plugin_small.html"); // 10x10 plugin + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); +}); + +// Test that the overlay is hidden for "small" plugin elements and is shown +// once they are resized to a size that can hold the overlay +add_task(function* () { + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "Test 2, Should have a click-to-play notification"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(!(overlay && overlay.classList.contains("visible")), + "Test 2, overlay should be hidden."); + }); +}); + +add_task(function* () { + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + plugin.style.width = "300px"; + }); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(!(overlay && overlay.classList.contains("visible")), + "Test 3, overlay should be hidden."); + }); +}); + + +add_task(function* () { + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + plugin.style.height = "300px"; + }); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + content.document.getElementById("test").clientTop; + }); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(overlay && overlay.classList.contains("visible"), + "Test 4, overlay should be visible."); + }); +}); + +add_task(function* () { + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + plugin.style.width = "10px"; + plugin.style.height = "10px"; + }); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + content.document.getElementById("test").clientTop; + }); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(!(overlay && overlay.classList.contains("visible")), + "Test 5, overlay should be hidden."); + }); +}); + +add_task(function* () { + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + plugin.style.height = "300px"; + plugin.style.width = "300px"; + }); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + content.document.getElementById("test").clientTop; + }); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(overlay && overlay.classList.contains("visible"), + "Test 6, overlay should be visible."); + }); +}); diff --git a/browser/base/content/test/plugins/browser_CTP_zoom.js b/browser/base/content/test/plugins/browser_CTP_zoom.js new file mode 100644 index 000000000..8b353232d --- /dev/null +++ b/browser/base/content/test/plugins/browser_CTP_zoom.js @@ -0,0 +1,62 @@ +"use strict"; + +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); + +var gTestBrowser = null; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + FullZoom.reset(); // must be called before closing the tab we zoomed! + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!popupNotification, "Test 1, Should not have a click-to-play notification"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_zoom.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); +}); + +// Enlarges the zoom level 4 times and tests that the overlay is +// visible after each enlargement. +add_task(function* () { + for (let count = 0; count < 4; count++) { + + FullZoom.enlarge(); + + // Reload the page + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_zoom.html"); + yield promiseUpdatePluginBindings(gTestBrowser); + yield ContentTask.spawn(gTestBrowser, { count }, function* (args) { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(overlay && overlay.classList.contains("visible"), + "Overlay should be visible for zoom change count " + args.count); + }); + } +}); + + diff --git a/browser/base/content/test/plugins/browser_blocking.js b/browser/base/content/test/plugins/browser_blocking.js new file mode 100644 index 000000000..334ed9f2e --- /dev/null +++ b/browser/base/content/test/plugins/browser_blocking.js @@ -0,0 +1,349 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + +function updateAllTestPlugins(aState) { + setTestPluginEnabledState(aState, "Test Plug-in"); + setTestPluginEnabledState(aState, "Second Test Plug-in"); +} + +add_task(function* () { + registerCleanupFunction(Task.async(function*() { + clearAllPluginPermissions(); + updateAllTestPlugins(Ci.nsIPluginTag.STATE_ENABLED); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + resetBlocklist(); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + })); +}); + +add_task(function* () { + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + // Prime the content process + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html>hi</html>"); + + // Make sure the blocklist service(s) are running + Components.classes["@mozilla.org/extensions/blocklist;1"] + .getService(Components.interfaces.nsIBlocklistService); + let exmsg = yield promiseInitContentBlocklistSvc(gBrowser.selectedBrowser); + ok(!exmsg, "exception: " + exmsg); +}); + +add_task(function* () { + // enable hard blocklisting for the next test + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginHard.xml", gTestBrowser); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + let notification = PopupNotifications.getNotification("click-to-play-plugins"); + ok(notification.dismissed, "Test 5: The plugin notification should be dismissed by default"); + + yield promiseForNotificationShown(notification); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, "Test 5, plugin fallback type should be PLUGIN_BLOCKLISTED"); + + is(notification.options.pluginData.size, 1, "Test 5: Only the blocked plugin should be present in the notification"); + ok(PopupNotifications.panel.firstChild._buttonContainer.hidden, "Part 5: The blocked plugins notification should not have any buttons visible."); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); +}); + +// Tests a vulnerable, updatable plugin + +add_task(function* () { + // enable hard blocklisting of test + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginVulnerableUpdatable.xml", gTestBrowser); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, + "Test 18a, plugin fallback type should be PLUGIN_VULNERABLE_UPDATABLE"); + ok(!pluginInfo.activated, "Test 18a, Plugin should not be activated"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(overlay && overlay.classList.contains("visible"), + "Test 18a, Plugin overlay should exist, not be hidden"); + + let updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink"); + Assert.ok(updateLink.style.visibility != "hidden", + "Test 18a, Plugin should have an update link"); + }); + + let promise = waitForEvent(gBrowser.tabContainer, "TabOpen", null, true); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink"); + let bounds = updateLink.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + yield promise; + + promise = waitForEvent(gBrowser.tabContainer, "TabClose", null, true); + gBrowser.removeCurrentTab(); + yield promise; +}); + +add_task(function* () { + // clicking the update link should not activate the plugin + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, + "Test 18a, plugin fallback type should be PLUGIN_VULNERABLE_UPDATABLE"); + ok(!pluginInfo.activated, "Test 18b, Plugin should not be activated"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(overlay && overlay.classList.contains("visible"), + "Test 18b, Plugin overlay should exist, not be hidden"); + }); +}); + +// Tests a vulnerable plugin with no update +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginVulnerableNoUpdate.xml", gTestBrowser); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 18c, Should have a click-to-play notification"); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE, + "Test 18c, plugin fallback type should be PLUGIN_VULNERABLE_NO_UPDATE"); + ok(!pluginInfo.activated, "Test 18c, Plugin should not be activated"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(overlay && overlay.classList.contains("visible"), + "Test 18c, Plugin overlay should exist, not be hidden"); + + let updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink"); + Assert.ok(updateLink && updateLink.style.display != "block", + "Test 18c, Plugin should not have an update link"); + }); + + // check that click "Always allow" works with blocked plugins + yield promiseForNotificationShown(notification); + + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE, + "Test 18c, plugin fallback type should be PLUGIN_VULNERABLE_NO_UPDATE"); + ok(pluginInfo.activated, "Test 18c, Plugin should be activated"); + let enabledState = getTestPluginEnabledState(); + ok(enabledState, "Test 18c, Plugin enabled state should be STATE_CLICKTOPLAY"); +}); + +// continue testing "Always allow", make sure it sticks. +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 18d, Waited too long for plugin to activate"); + + clearAllPluginPermissions(); +}); + +// clicking the in-content overlay of a vulnerable plugin should bring +// up the notification and not directly activate the plugin +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let 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"); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 18f, Waited too long for plugin to activate"); + + var oldEventCallback = notification.options.eventCallback; + let promise = promiseForCondition(() => oldEventCallback == null); + notification.options.eventCallback = function() { + if (oldEventCallback) { + oldEventCallback(); + } + oldEventCallback = null; + }; + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let bounds = plugin.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + yield promise; + + ok(notification, "Test 18g, Should have a click-to-play notification"); + ok(!notification.dismissed, "Test 18g, notification should be open"); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 18g, Plugin should not be activated"); +}); + +// Test that "always allow"-ing a plugin will not allow it when it becomes +// blocklisted. +add_task(function* () { + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 24a, Should have a click-to-play notification"); + + // Plugin should start as CTP + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, + "Test 24a, plugin fallback type should be PLUGIN_CLICK_TO_PLAY"); + ok(!pluginInfo.activated, "Test 24a, Plugin should not be active."); + + // simulate "always allow" + yield promiseForNotificationShown(notification); + + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 24a, Plugin should be active."); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginVulnerableUpdatable.xml", gTestBrowser); +}); + +// the plugin is now blocklisted, so it should not automatically load +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 24b, Should have a click-to-play notification"); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, + "Test 24b, plugin fallback type should be PLUGIN_VULNERABLE_UPDATABLE"); + ok(!pluginInfo.activated, "Test 24b, Plugin should not be active."); + + // simulate "always allow" + yield promiseForNotificationShown(notification); + + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 24b, Plugin should be active."); + + clearAllPluginPermissions(); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); +}); + +// Plugin sync removal test. Note this test produces a notification drop down since +// the plugin we add has zero dims. +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_syncRemoved.html"); + + // Maybe there some better trick here, we need to wait for the page load, then + // wait for the js to execute in the page. + yield waitForMs(500); + + let notification = PopupNotifications.getNotification("click-to-play-plugins"); + ok(notification, "Test 25: There should be a plugin notification even if the plugin was immediately removed"); + ok(notification.dismissed, "Test 25: The notification should be dismissed by default"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html>hi</html>"); +}); + +// Tests a page with a blocked plugin in it and make sure the infoURL property +// the blocklist file gets used. +add_task(function* () { + clearAllPluginPermissions(); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginInfoURL.xml", gTestBrowser); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins"); + + // Since the plugin notification is dismissed by default, reshow it. + yield promiseForNotificationShown(notification); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, + "Test 26, plugin fallback type should be PLUGIN_BLOCKLISTED"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let plugin = content.document.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.ok(!objLoadingContent.activated, "Plugin should not be activated."); + }); + + const testUrl = "http://test.url.com/"; + + let firstPanelChild = PopupNotifications.panel.firstChild; + let infoLink = document.getAnonymousElementByAttribute(firstPanelChild, "anonid", + "click-to-play-plugins-notification-link"); + is(infoLink.href, testUrl, + "Test 26, the notification URL needs to match the infoURL from the blocklist file."); +}); + diff --git a/browser/base/content/test/plugins/browser_blocklist_content.js b/browser/base/content/test/plugins/browser_blocklist_content.js new file mode 100644 index 000000000..bf4e159bc --- /dev/null +++ b/browser/base/content/test/plugins/browser_blocklist_content.js @@ -0,0 +1,104 @@ +var gTestBrowser = null; +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gChromeRoot = getRootDirectory(gTestPath); + +add_task(function* () { + registerCleanupFunction(Task.async(function*() { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + resetBlocklist(); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + })); +}); + +add_task(function* () { + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + + // Prime the blocklist service, the remote service doesn't launch on startup. + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html></html>"); + let exmsg = yield promiseInitContentBlocklistSvc(gBrowser.selectedBrowser); + ok(!exmsg, "exception: " + exmsg); +}); + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let test = content.document.getElementById("test"); + Assert.ok(test.activated, "task 1a: test plugin should be activated!"); + }); +}); + +// Load a fresh page, load a new plugin blocklist, then load the same page again. +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html>GO!</html>"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginHard.xml", gTestBrowser); + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let test = content.document.getElementById("test"); + ok(!test.activated, "task 2a: test plugin shouldn't activate!"); + }); +}); + +// Unload the block list and lets do this again, only this time lets +// hack around in the content blocklist service maliciously. +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html>GO!</html>"); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + + // Hack the planet! Load our blocklist shim, so we can mess with blocklist + // return results in the content process. Active until we close our tab. + let mm = gTestBrowser.messageManager; + info("test 3a: loading " + gChromeRoot + "blocklist_proxy.js" + "\n"); + mm.loadFrameScript(gChromeRoot + "blocklist_proxy.js", true); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let test = content.document.getElementById("test"); + Assert.ok(test.activated, "task 3a: test plugin should be activated!"); + }); +}); + +// Load a fresh page, load a new plugin blocklist, then load the same page again. +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html>GO!</html>"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginHard.xml", gTestBrowser); + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let test = content.document.getElementById("test"); + Assert.ok(!test.activated, "task 4a: test plugin shouldn't activate!"); + }); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); +}); diff --git a/browser/base/content/test/plugins/browser_bug743421.js b/browser/base/content/test/plugins/browser_bug743421.js new file mode 100644 index 000000000..966e7b012 --- /dev/null +++ b/browser/base/content/test/plugins/browser_bug743421.js @@ -0,0 +1,119 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; + +add_task(function* () { + registerCleanupFunction(Task.async(function*() { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + resetBlocklist(); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + })); +}); + +add_task(function* () { + let newTab = gBrowser.addTab(); + gBrowser.selectedTab = newTab; + gTestBrowser = gBrowser.selectedBrowser; + + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in"); + + // Prime the blocklist service, the remote service doesn't launch on startup. + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html></html>"); + + let exmsg = yield promiseInitContentBlocklistSvc(gBrowser.selectedBrowser); + ok(!exmsg, "exception: " + exmsg); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); +}); + +// Tests that navigation within the page and the window.history API doesn't break click-to-play state. +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_add_dynamically.html"); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!notification, "Test 1a, Should not have a click-to-play notification"); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin()); + }); + + yield promisePopupNotification("click-to-play-plugins"); +}); + +add_task(function* () { + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementsByTagName("embed")[0]; + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.ok(!objLoadingContent.activated, "Test 1b, Plugin should not be activated"); + }); + + // Click the activate button on doorhanger to make sure it works + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + + yield promiseForNotificationShown(notification); + + PopupNotifications.panel.firstChild._primaryButton.click(); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementsByTagName("embed")[0]; + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.ok(objLoadingContent.activated, "Test 1b, Plugin should be activated"); + }); +}); + +add_task(function* () { + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 1c, Should still have a click-to-play notification"); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin()); + let plugin = content.document.getElementsByTagName("embed")[1]; + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.ok(objLoadingContent.activated, + "Test 1c, Newly inserted plugin in activated page should be activated"); + }); +}); + +add_task(function* () { + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementsByTagName("embed")[1]; + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.ok(objLoadingContent.activated, "Test 1d, Plugin should be activated"); + + let promise = ContentTaskUtils.waitForEvent(content, "hashchange"); + content.location += "#anchorNavigation"; + yield promise; + }); +}); + +add_task(function* () { + yield ContentTask.spawn(gTestBrowser, {}, function* () { + new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin()); + let plugin = content.document.getElementsByTagName("embed")[2]; + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.ok(objLoadingContent.activated, "Test 1e, Plugin should be activated"); + }); +}); + +add_task(function* () { + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementsByTagName("embed")[2]; + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.ok(objLoadingContent.activated, "Test 1f, Plugin should be activated"); + + content.history.replaceState({}, "", "replacedState"); + new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin()); + plugin = content.document.getElementsByTagName("embed")[3]; + objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + Assert.ok(objLoadingContent.activated, "Test 1g, Plugin should be activated"); + }); +}); diff --git a/browser/base/content/test/plugins/browser_bug744745.js b/browser/base/content/test/plugins/browser_bug744745.js new file mode 100644 index 000000000..c9f552a4e --- /dev/null +++ b/browser/base/content/test/plugins/browser_bug744745.js @@ -0,0 +1,50 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; +var gNumPluginBindingsAttached = 0; + +function pluginBindingAttached() { + gNumPluginBindingsAttached++; + if (gNumPluginBindingsAttached != 1) { + ok(false, "if we've gotten here, something is quite wrong"); + } +} + +add_task(function* () { + registerCleanupFunction(function () { + gTestBrowser.removeEventListener("PluginBindingAttached", pluginBindingAttached, true, true); + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); +}); + +add_task(function* () { + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + Services.prefs.setBoolPref("plugins.click_to_play", true); + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + gTestBrowser.addEventListener("PluginBindingAttached", pluginBindingAttached, true, true); + + let testRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); + yield promiseTabLoadEvent(gBrowser.selectedTab, testRoot + "plugin_bug744745.html"); + + yield promiseForCondition(function () { return gNumPluginBindingsAttached == 1; }); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("test"); + if (!plugin) { + Assert.ok(false, "plugin element not available."); + return; + } + // We can't use MochiKit's routine + let style = content.getComputedStyle(plugin); + Assert.ok(("opacity" in style) && style.opacity == 1, "plugin style properly configured."); + }); +}); diff --git a/browser/base/content/test/plugins/browser_bug787619.js b/browser/base/content/test/plugins/browser_bug787619.js new file mode 100644 index 000000000..bfd52258c --- /dev/null +++ b/browser/base/content/test/plugins/browser_bug787619.js @@ -0,0 +1,65 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; +var gWrapperClickCount = 0; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + let testRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); + yield promiseTabLoadEvent(gBrowser.selectedTab, testRoot + "plugin_bug787619.html"); + + // 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. + yield promiseUpdatePluginBindings(gTestBrowser); + + // check plugin state + let pluginInfo = yield promiseForPluginInfo("plugin"); + ok(!pluginInfo.activated, "1a plugin should not be activated"); + + // click the overlay to prompt + let promise = promisePopupNotification("click-to-play-plugins"); + yield ContentTask.spawn(gTestBrowser, {}, function* () { + let plugin = content.document.getElementById("plugin"); + let bounds = plugin.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + yield promise; + + // check plugin state + pluginInfo = yield promiseForPluginInfo("plugin"); + ok(!pluginInfo.activated, "1b plugin should not be activated"); + + let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed && + PopupNotifications.panel.firstChild; + yield promiseForCondition(condition); + PopupNotifications.panel.firstChild._primaryButton.click(); + + // check plugin state + pluginInfo = yield promiseForPluginInfo("plugin"); + ok(pluginInfo.activated, "plugin should be activated"); + + is(gWrapperClickCount, 0, 'wrapper should not have received any clicks'); +}); diff --git a/browser/base/content/test/plugins/browser_bug797677.js b/browser/base/content/test/plugins/browser_bug797677.js new file mode 100644 index 000000000..1ae9f5047 --- /dev/null +++ b/browser/base/content/test/plugins/browser_bug797677.js @@ -0,0 +1,43 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; +var gConsoleErrors = 0; + +var Cc = Components.classes; +var Ci = Components.interfaces; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + consoleService.unregisterListener(errorListener); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + let consoleService = Cc["@mozilla.org/consoleservice;1"] + .getService(Ci.nsIConsoleService); + let errorListener = { + observe: function(aMessage) { + if (aMessage.message.includes("NS_ERROR_FAILURE")) + gConsoleErrors++; + } + }; + consoleService.registerListener(errorListener); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_bug797677.html"); + + let pluginInfo = yield promiseForPluginInfo("plugin"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED, "plugin should not have been found."); + + // simple cpows + yield ContentTask.spawn(gTestBrowser, null, function() { + let plugin = content.document.getElementById("plugin"); + ok(plugin, "plugin should be in the page"); + }); + is(gConsoleErrors, 0, "should have no console errors"); +}); diff --git a/browser/base/content/test/plugins/browser_bug812562.js b/browser/base/content/test/plugins/browser_bug812562.js new file mode 100644 index 000000000..be7b00b22 --- /dev/null +++ b/browser/base/content/test/plugins/browser_bug812562.js @@ -0,0 +1,80 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; + +add_task(function* () { + registerCleanupFunction(Task.async(function*() { + clearAllPluginPermissions(); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + resetBlocklist(); + Services.prefs.clearUserPref("plugins.click_to_play"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + })); + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + Services.prefs.setBoolPref("plugins.click_to_play", true); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + // Prime the blocklist service, the remote service doesn't launch on startup. + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html></html>"); + let exmsg = yield promiseInitContentBlocklistSvc(gBrowser.selectedBrowser); + ok(!exmsg, "exception: " + exmsg); +}); + +// Tests that the going back will reshow the notification for click-to-play +// blocklisted plugins +add_task(function* () { + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginVulnerableUpdatable.xml", gTestBrowser); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "test part 1: Should have a click-to-play notification"); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "plugin should be marked as VULNERABLE"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + Assert.ok(!!content.document.getElementById("test"), + "test part 1: plugin should not be activated"); + }); + + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html></html>"); +}); + +add_task(function* () { + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!popupNotification, "test part 2: Should not have a click-to-play notification"); + yield ContentTask.spawn(gTestBrowser, null, function* () { + Assert.ok(!content.document.getElementById("test"), + "test part 2: plugin should not be activated"); + }); + + let obsPromise = TestUtils.topicObserved("PopupNotifications-updateNotShowing"); + let overlayPromise = promisePopupNotification("click-to-play-plugins"); + gTestBrowser.goBack(); + yield obsPromise; + yield overlayPromise; +}); + +add_task(function* () { + yield promiseUpdatePluginBindings(gTestBrowser); + + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "test part 3: Should have a click-to-play notification"); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "plugin should be marked as VULNERABLE"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + Assert.ok(!!content.document.getElementById("test"), + "test part 3: plugin should not be activated"); + }); +}); diff --git a/browser/base/content/test/plugins/browser_bug818118.js b/browser/base/content/test/plugins/browser_bug818118.js new file mode 100644 index 000000000..9dd6e22e7 --- /dev/null +++ b/browser/base/content/test/plugins/browser_bug818118.js @@ -0,0 +1,40 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_both.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "should have a click-to-play notification"); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "plugin should be click to play"); + ok(!pluginInfo.activated, "plugin should not be activated"); + + yield ContentTask.spawn(gTestBrowser, null, () => { + let unknown = content.document.getElementById("unknown"); + ok(unknown, "should have unknown plugin in page"); + }); +}); diff --git a/browser/base/content/test/plugins/browser_bug820497.js b/browser/base/content/test/plugins/browser_bug820497.js new file mode 100644 index 000000000..b2e0f5268 --- /dev/null +++ b/browser/base/content/test/plugins/browser_bug820497.js @@ -0,0 +1,71 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; +var gNumPluginBindingsAttached = 0; + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in"); + + gTestBrowser.addEventListener("PluginBindingAttached", function () { gNumPluginBindingsAttached++ }, true, true); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_bug820497.html"); + + yield promiseForCondition(function () { return gNumPluginBindingsAttached == 1; }); + + yield ContentTask.spawn(gTestBrowser, null, () => { + // Note we add the second plugin in the code farther down, so there's + // no way we got here with anything but one plugin loaded. + let doc = content.document; + let testplugin = doc.getElementById("test"); + ok(testplugin, "should have test plugin"); + let secondtestplugin = doc.getElementById("secondtest"); + ok(!secondtestplugin, "should not yet have second test plugin"); + }); + + yield promisePopupNotification("click-to-play-plugins"); + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "should have a click-to-play notification"); + + yield promiseForNotificationShown(notification); + + is(notification.options.pluginData.size, 1, "should be 1 type of plugin in the popup notification"); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + XPCNativeWrapper.unwrap(content).addSecondPlugin(); + }); + + yield promiseForCondition(function () { return gNumPluginBindingsAttached == 2; }); + + yield ContentTask.spawn(gTestBrowser, null, () => { + let doc = content.document; + let testplugin = doc.getElementById("test"); + ok(testplugin, "should have test plugin"); + let secondtestplugin = doc.getElementById("secondtest"); + ok(secondtestplugin, "should have second test plugin"); + }); + + notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + + ok(notification, "should have popup notification"); + + yield promiseForNotificationShown(notification); + + is(notification.options.pluginData.size, 2, "aited too long for 2 types of plugins in popup notification"); +}); diff --git a/browser/base/content/test/plugins/browser_clearplugindata.html b/browser/base/content/test/plugins/browser_clearplugindata.html new file mode 100644 index 000000000..243350ba4 --- /dev/null +++ b/browser/base/content/test/plugins/browser_clearplugindata.html @@ -0,0 +1,30 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html> + <head> + <title>Plugin Clear Site Data sanitize test</title> + + <embed id="plugin1" type="application/x-test" width="200" height="200"></embed> + + <script type="application/javascript"> + function testSteps() + { + // Make sure clearing by timerange is supported. + var p = document.getElementById("plugin1"); + p.setSitesWithDataCapabilities(true); + + p.setSitesWithData( + "foo.com:0:5," + + "bar.com:0:100," + + "baz.com:1:5," + + "qux.com:1:100" + ); + } + </script> + </head> + + <body onload="testSteps();"></body> + +</html> diff --git a/browser/base/content/test/plugins/browser_clearplugindata.js b/browser/base/content/test/plugins/browser_clearplugindata.js new file mode 100644 index 000000000..69d474fed --- /dev/null +++ b/browser/base/content/test/plugins/browser_clearplugindata.js @@ -0,0 +1,127 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); +var gTestBrowser = null; + +// Test clearing plugin data using sanitize.js. +const testURL1 = gTestRoot + "browser_clearplugindata.html"; +const testURL2 = gTestRoot + "browser_clearplugindata_noage.html"; + +var tempScope = {}; +Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader) + .loadSubScript("chrome://browser/content/sanitize.js", tempScope); +var Sanitizer = tempScope.Sanitizer; + +const pluginHostIface = Ci.nsIPluginHost; +var pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); +pluginHost.QueryInterface(pluginHostIface); + +var pluginTag = getTestPlugin(); +var sanitizer = null; + +function stored(needles) { + let something = pluginHost.siteHasData(this.pluginTag, null); + if (!needles) + return something; + + if (!something) + return false; + + for (let i = 0; i < needles.length; ++i) { + if (!pluginHost.siteHasData(this.pluginTag, needles[i])) + return false; + } + return true; +} + +add_task(function* () { + registerCleanupFunction(function () { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + if (gTestBrowser) { + gBrowser.removeCurrentTab(); + } + window.focus(); + gTestBrowser = null; + }); +}); + +add_task(function* () { + Services.prefs.setBoolPref("plugins.click_to_play", true); + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + + sanitizer = new Sanitizer(); + sanitizer.ignoreTimespan = false; + sanitizer.prefDomain = "privacy.cpd."; + let itemPrefs = gPrefService.getBranch(sanitizer.prefDomain); + itemPrefs.setBoolPref("history", false); + itemPrefs.setBoolPref("downloads", false); + itemPrefs.setBoolPref("cache", false); + itemPrefs.setBoolPref("cookies", true); // plugin data + itemPrefs.setBoolPref("formdata", false); + itemPrefs.setBoolPref("offlineApps", false); + itemPrefs.setBoolPref("passwords", false); + itemPrefs.setBoolPref("sessions", false); + itemPrefs.setBoolPref("siteSettings", false); +}); + +add_task(function* () { + // Load page to set data for the plugin. + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + yield promiseTabLoadEvent(gBrowser.selectedTab, testURL1); + + yield promiseUpdatePluginBindings(gTestBrowser); + + ok(stored(["foo.com", "bar.com", "baz.com", "qux.com"]), + "Data stored for sites"); + + // Clear 20 seconds ago + let now_uSec = Date.now() * 1000; + sanitizer.range = [now_uSec - 20*1000000, now_uSec]; + yield sanitizer.sanitize(); + + ok(stored(["bar.com", "qux.com"]), "Data stored for sites"); + ok(!stored(["foo.com"]), "Data cleared for foo.com"); + ok(!stored(["baz.com"]), "Data cleared for baz.com"); + + // Clear everything + sanitizer.range = null; + yield sanitizer.sanitize(); + + ok(!stored(null), "All data cleared"); + + gBrowser.removeCurrentTab(); + gTestBrowser = null; +}); + +add_task(function* () { + // Load page to set data for the plugin. + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + yield promiseTabLoadEvent(gBrowser.selectedTab, testURL2); + + yield promiseUpdatePluginBindings(gTestBrowser); + + ok(stored(["foo.com", "bar.com", "baz.com", "qux.com"]), + "Data stored for sites"); + + // Attempt to clear 20 seconds ago. The plugin will throw + // NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED, which should result in us + // clearing all data regardless of age. + let now_uSec = Date.now() * 1000; + sanitizer.range = [now_uSec - 20*1000000, now_uSec]; + yield sanitizer.sanitize(); + + ok(!stored(null), "All data cleared"); + + gBrowser.removeCurrentTab(); + gTestBrowser = null; +}); + diff --git a/browser/base/content/test/plugins/browser_clearplugindata_noage.html b/browser/base/content/test/plugins/browser_clearplugindata_noage.html new file mode 100644 index 000000000..820979541 --- /dev/null +++ b/browser/base/content/test/plugins/browser_clearplugindata_noage.html @@ -0,0 +1,30 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html> + <head> + <title>Plugin Clear Site Data sanitize test without age</title> + + <embed id="plugin1" type="application/x-test" width="200" height="200"></embed> + + <script type="application/javascript"> + function testSteps() + { + // Make sure clearing by timerange is disabled. + var p = document.getElementById("plugin1"); + p.setSitesWithDataCapabilities(false); + + p.setSitesWithData( + "foo.com:0:5," + + "bar.com:0:100," + + "baz.com:1:5," + + "qux.com:1:100" + ); + } + </script> + </head> + + <body onload="testSteps();"></body> + +</html> diff --git a/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js b/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js new file mode 100644 index 000000000..bdca32e70 --- /dev/null +++ b/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js @@ -0,0 +1,34 @@ +/** + * Test that the notification bar for crashed GMPs works. + */ +add_task(function*() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:blank", + }, function* (browser) { + yield ContentTask.spawn(browser, null, function* () { + const GMP_CRASH_EVENT = { + pluginID: 1, + pluginName: "GlobalTestPlugin", + submittedCrashReport: false, + bubbles: true, + cancelable: true, + gmpPlugin: true, + }; + + let crashEvent = new content.PluginCrashedEvent("PluginCrashed", + GMP_CRASH_EVENT); + content.dispatchEvent(crashEvent); + }); + + let notification = yield waitForNotificationBar("plugin-crashed", browser); + + let notificationBox = gBrowser.getNotificationBox(browser); + ok(notification, "Infobar was shown."); + is(notification.priority, notificationBox.PRIORITY_WARNING_MEDIUM, + "Correct priority."); + is(notification.getAttribute("label"), + "The GlobalTestPlugin plugin has crashed.", + "Correct message."); + }); +}); diff --git a/browser/base/content/test/plugins/browser_pageInfo_plugins.js b/browser/base/content/test/plugins/browser_pageInfo_plugins.js new file mode 100644 index 000000000..0d941e0fa --- /dev/null +++ b/browser/base/content/test/plugins/browser_pageInfo_plugins.js @@ -0,0 +1,191 @@ +var gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gPageInfo = null; +var gNextTest = null; +var gTestBrowser = null; +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"] + .getService(Components.interfaces.nsIPluginHost); +var gPermissionManager = Components.classes["@mozilla.org/permissionmanager;1"] + .getService(Components.interfaces.nsIPermissionManager); +var gTestPermissionString = gPluginHost.getPermissionStringForType("application/x-test"); +var gSecondTestPermissionString = gPluginHost.getPermissionStringForType("application/x-second-test"); + +function doOnPageLoad(url, continuation) { + gNextTest = continuation; + gTestBrowser.addEventListener("load", pageLoad, true); + gTestBrowser.contentWindow.location = url; +} + +function pageLoad() { + gTestBrowser.removeEventListener("load", pageLoad); + // 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 + executeSoon(gNextTest); +} + +function doOnOpenPageInfo(continuation) { + Services.obs.addObserver(pageInfoObserve, "page-info-dialog-loaded", false); + gNextTest = continuation; + // An explanation: it looks like the test harness complains about leaked + // windows if we don't keep a reference to every window we've opened. + // So, don't reuse pointers to opened Page Info windows - simply append + // to this list. + gPageInfo = BrowserPageInfo(null, "permTab"); +} + +function pageInfoObserve(win, topic, data) { + Services.obs.removeObserver(pageInfoObserve, "page-info-dialog-loaded"); + gPageInfo.onFinished.push(() => executeSoon(gNextTest)); +} + +function finishTest() { + gPermissionManager.remove(makeURI("http://127.0.0.1:8888/"), gTestPermissionString); + gPermissionManager.remove(makeURI("http://127.0.0.1:8888/"), gSecondTestPermissionString); + Services.prefs.clearUserPref("plugins.click_to_play"); + gBrowser.removeCurrentTab(); + + gPageInfo = null; + gNextTest = null; + gTestBrowser = null; + gPluginHost = null; + gPermissionManager = null; + + executeSoon(finish); +} + +function test() { + waitForExplicitFinish(); + Services.prefs.setBoolPref("plugins.click_to_play", true); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + gPermissionManager.remove(makeURI("http://127.0.0.1:8888/"), gTestPermissionString); + gPermissionManager.remove(makeURI("http://127.0.0.1:8888/"), gSecondTestPermissionString); + doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart1a); +} + +// The first test plugin is CtP and the second test plugin is enabled. +function testPart1a() { + let test = gTestBrowser.contentDocument.getElementById("test"); + let objLoadingContent = test.QueryInterface(Ci.nsIObjectLoadingContent); + ok(!objLoadingContent.activated, "part 1a: Test plugin should not be activated"); + let secondtest = gTestBrowser.contentDocument.getElementById("secondtestA"); + objLoadingContent = secondtest.QueryInterface(Ci.nsIObjectLoadingContent); + ok(objLoadingContent.activated, "part 1a: Second Test plugin should be activated"); + + doOnOpenPageInfo(testPart1b); +} + +function testPart1b() { + let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup"); + let testRadioDefault = gPageInfo.document.getElementById(gTestPermissionString + "#0"); + + is(testRadioGroup.selectedItem, testRadioDefault, "part 1b: Test radio group should be set to 'Default'"); + let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1"); + testRadioGroup.selectedItem = testRadioAllow; + testRadioAllow.doCommand(); + + let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup"); + let secondtestRadioDefault = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0"); + is(secondtestRadioGroup.selectedItem, secondtestRadioDefault, "part 1b: Second Test radio group should be set to 'Default'"); + let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#3"); + secondtestRadioGroup.selectedItem = secondtestRadioAsk; + secondtestRadioAsk.doCommand(); + + doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart2); +} + +// Now, the Test plugin should be allowed, and the Test2 plugin should be CtP +function testPart2() { + let test = gTestBrowser.contentDocument.getElementById("test"). + QueryInterface(Ci.nsIObjectLoadingContent); + ok(test.activated, "part 2: Test plugin should be activated"); + + let secondtest = gTestBrowser.contentDocument.getElementById("secondtestA"). + QueryInterface(Ci.nsIObjectLoadingContent); + ok(!secondtest.activated, "part 2: Second Test plugin should not be activated"); + is(secondtest.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, + "part 2: Second test plugin should be click-to-play."); + + let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup"); + let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1"); + is(testRadioGroup.selectedItem, testRadioAllow, "part 2: Test radio group should be set to 'Allow'"); + let testRadioBlock = gPageInfo.document.getElementById(gTestPermissionString + "#2"); + testRadioGroup.selectedItem = testRadioBlock; + testRadioBlock.doCommand(); + + let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup"); + let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#3"); + is(secondtestRadioGroup.selectedItem, secondtestRadioAsk, "part 2: Second Test radio group should be set to 'Always Ask'"); + let secondtestRadioBlock = gPageInfo.document.getElementById(gSecondTestPermissionString + "#2"); + secondtestRadioGroup.selectedItem = secondtestRadioBlock; + secondtestRadioBlock.doCommand(); + + doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart3); +} + +// Now, all the things should be blocked +function testPart3() { + let test = gTestBrowser.contentDocument.getElementById("test"). + QueryInterface(Ci.nsIObjectLoadingContent); + ok(!test.activated, "part 3: Test plugin should not be activated"); + is(test.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED, + "part 3: Test plugin should be marked as PLUGIN_DISABLED"); + + let secondtest = gTestBrowser.contentDocument.getElementById("secondtestA"). + QueryInterface(Ci.nsIObjectLoadingContent); + + ok(!secondtest.activated, "part 3: Second Test plugin should not be activated"); + is(secondtest.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED, + "part 3: Second test plugin should be marked as PLUGIN_DISABLED"); + + // reset permissions + gPermissionManager.remove(makeURI("http://127.0.0.1:8888/"), gTestPermissionString); + gPermissionManager.remove(makeURI("http://127.0.0.1:8888/"), gSecondTestPermissionString); + // check that changing the permissions affects the radio state in the + // open Page Info window + let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup"); + let testRadioDefault = gPageInfo.document.getElementById(gTestPermissionString + "#0"); + is(testRadioGroup.selectedItem, testRadioDefault, "part 3: Test radio group should be set to 'Default'"); + let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup"); + let secondtestRadioDefault = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0"); + is(secondtestRadioGroup.selectedItem, secondtestRadioDefault, "part 3: Second Test radio group should be set to 'Default'"); + + doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart4a); +} + +// Now test that setting permission directly (as from the popup notification) +// immediately influences Page Info. +function testPart4a() { + // simulate "allow" from the doorhanger + gPermissionManager.add(gTestBrowser.currentURI, gTestPermissionString, Ci.nsIPermissionManager.ALLOW_ACTION); + gPermissionManager.add(gTestBrowser.currentURI, gSecondTestPermissionString, Ci.nsIPermissionManager.ALLOW_ACTION); + + // check (again) that changing the permissions affects the radio state in the + // open Page Info window + let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup"); + let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1"); + is(testRadioGroup.selectedItem, testRadioAllow, "part 4a: Test radio group should be set to 'Allow'"); + let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup"); + let secondtestRadioAllow = gPageInfo.document.getElementById(gSecondTestPermissionString + "#1"); + is(secondtestRadioGroup.selectedItem, secondtestRadioAllow, "part 4a: Second Test radio group should be set to 'Always Allow'"); + + // now close Page Info and see that it opens with the right settings + gPageInfo.close(); + doOnOpenPageInfo(testPart4b); +} + +// check that "always allow" resulted in the radio buttons getting set to allow +function testPart4b() { + let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup"); + let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1"); + is(testRadioGroup.selectedItem, testRadioAllow, "part 4b: Test radio group should be set to 'Allow'"); + + let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup"); + let secondtestRadioAllow = gPageInfo.document.getElementById(gSecondTestPermissionString + "#1"); + is(secondtestRadioGroup.selectedItem, secondtestRadioAllow, "part 4b: Second Test radio group should be set to 'Allow'"); + + Services.prefs.setBoolPref("plugins.click_to_play", false); + gPageInfo.close(); + finishTest(); +} diff --git a/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js b/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js new file mode 100644 index 000000000..ab4743f6f --- /dev/null +++ b/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js @@ -0,0 +1,207 @@ +Cu.import("resource://gre/modules/CrashSubmit.jsm", this); + +const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs"; + +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gTestBrowser = null; +var config = {}; + +add_task(function* () { + // The test harness sets MOZ_CRASHREPORTER_NO_REPORT, which disables plugin + // crash reports. This test needs them enabled. The test also needs a mock + // report server, and fortunately one is already set up by toolkit/ + // crashreporter/test/Makefile.in. Assign its URL to MOZ_CRASHREPORTER_URL, + // which CrashSubmit.jsm uses as a server override. + let env = Components.classes["@mozilla.org/process/environment;1"] + .getService(Components.interfaces.nsIEnvironment); + let noReport = env.get("MOZ_CRASHREPORTER_NO_REPORT"); + let serverUrl = env.get("MOZ_CRASHREPORTER_URL"); + env.set("MOZ_CRASHREPORTER_NO_REPORT", ""); + env.set("MOZ_CRASHREPORTER_URL", SERVER_URL); + + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + // Crash immediately + Services.prefs.setIntPref("dom.ipc.plugins.timeoutSecs", 0); + + registerCleanupFunction(Task.async(function*() { + Services.prefs.clearUserPref("dom.ipc.plugins.timeoutSecs"); + env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport); + env.set("MOZ_CRASHREPORTER_URL", serverUrl); + env = null; + config = null; + gTestBrowser = null; + gBrowser.removeCurrentTab(); + window.focus(); + })); +}); + +add_task(function* () { + config = { + shouldSubmissionUIBeVisible: true, + comment: "", + urlOptIn: false + }; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED); + + let pluginCrashed = promisePluginCrashed(); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + // Wait for the plugin to crash + yield pluginCrashed; + + let crashReportStatus = TestUtils.topicObserved("crash-report-status", onSubmitStatus); + + // Test that the crash submission UI is actually visible and submit the crash report. + yield ContentTask.spawn(gTestBrowser, config, function* (aConfig) { + let doc = content.document; + let plugin = doc.getElementById("plugin"); + let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit"); + let submitButton = doc.getAnonymousElementByAttribute(plugin, "anonid", "submitButton"); + // Test that we don't send the URL when urlOptIn is false. + doc.getAnonymousElementByAttribute(plugin, "anonid", "submitURLOptIn").checked = aConfig.urlOptIn; + submitButton.click(); + Assert.equal(content.getComputedStyle(pleaseSubmit).display == "block", + aConfig.shouldSubmissionUIBeVisible, "The crash UI should be visible"); + }); + + yield crashReportStatus; +}); + +add_task(function* () { + config = { + shouldSubmissionUIBeVisible: true, + comment: "a test comment", + urlOptIn: true + }; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED); + + let pluginCrashed = promisePluginCrashed(); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + // Wait for the plugin to crash + yield pluginCrashed; + + let crashReportStatus = TestUtils.topicObserved("crash-report-status", onSubmitStatus); + + // Test that the crash submission UI is actually visible and submit the crash report. + yield ContentTask.spawn(gTestBrowser, config, function* (aConfig) { + let doc = content.document; + let plugin = doc.getElementById("plugin"); + let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit"); + let submitButton = doc.getAnonymousElementByAttribute(plugin, "anonid", "submitButton"); + // Test that we send the URL when urlOptIn is true. + doc.getAnonymousElementByAttribute(plugin, "anonid", "submitURLOptIn").checked = aConfig.urlOptIn; + doc.getAnonymousElementByAttribute(plugin, "anonid", "submitComment").value = aConfig.comment; + submitButton.click(); + Assert.equal(content.getComputedStyle(pleaseSubmit).display == "block", + aConfig.shouldSubmissionUIBeVisible, "The crash UI should be visible"); + }); + + yield crashReportStatus; +}); + +add_task(function* () { + config = { + shouldSubmissionUIBeVisible: false, + comment: "", + urlOptIn: true + }; + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED); + + let pluginCrashed = promisePluginCrashed(); + + // Make sure that the plugin container is too small to display the crash submission UI + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html?" + + encodeURIComponent(JSON.stringify({width: 300, height: 300}))); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + // Wait for the plugin to crash + yield pluginCrashed; + + // Test that the crash submission UI is not visible and do not submit a crash report. + yield ContentTask.spawn(gTestBrowser, config, function* (aConfig) { + let doc = content.document; + let plugin = doc.getElementById("plugin"); + let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit"); + Assert.equal(!!pleaseSubmit && content.getComputedStyle(pleaseSubmit).display == "block", + aConfig.shouldSubmissionUIBeVisible, "Plugin crash UI should not be visible"); + }); +}); + +function promisePluginCrashed() { + return new ContentTask.spawn(gTestBrowser, {}, function* () { + yield new Promise((resolve) => { + addEventListener("PluginCrashReporterDisplayed", function onPluginCrashed() { + removeEventListener("PluginCrashReporterDisplayed", onPluginCrashed); + resolve(); + }); + }); + }) +} + +function onSubmitStatus(aSubject, aData) { + // Wait for success or failed, doesn't matter which. + if (aData != "success" && aData != "failed") + return false; + + let propBag = aSubject.QueryInterface(Ci.nsIPropertyBag); + if (aData == "success") { + let remoteID = getPropertyBagValue(propBag, "serverCrashID"); + ok(!!remoteID, "serverCrashID should be set"); + + // Remove the submitted report file. + let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); + file.initWithPath(Services.crashmanager._submittedDumpsDir); + file.append(remoteID + ".txt"); + ok(file.exists(), "Submitted report file should exist"); + file.remove(false); + } + + let extra = getPropertyBagValue(propBag, "extra"); + ok(extra instanceof Ci.nsIPropertyBag, "Extra data should be property bag"); + + let val = getPropertyBagValue(extra, "PluginUserComment"); + if (config.comment) + is(val, config.comment, + "Comment in extra data should match comment in textbox"); + else + ok(val === undefined, + "Comment should be absent from extra data when textbox is empty"); + + val = getPropertyBagValue(extra, "PluginContentURL"); + if (config.urlOptIn) + is(val, gBrowser.currentURI.spec, + "URL in extra data should match browser URL when opt-in checked"); + else + ok(val === undefined, + "URL should be absent from extra data when opt-in not checked"); + + return true; +} + +function getPropertyBagValue(bag, key) { + try { + var val = bag.getProperty(key); + } + catch (e) { + if (e.result != Cr.NS_ERROR_FAILURE) { + throw e; + } + } + return val; +} diff --git a/browser/base/content/test/plugins/browser_pluginCrashReportNonDeterminism.js b/browser/base/content/test/plugins/browser_pluginCrashReportNonDeterminism.js new file mode 100644 index 000000000..42ef57314 --- /dev/null +++ b/browser/base/content/test/plugins/browser_pluginCrashReportNonDeterminism.js @@ -0,0 +1,254 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * With e10s, plugins must run in their own process. This means we have + * three processes at a minimum when we're running a plugin: + * + * 1) The main browser, or "chrome" process + * 2) The content process hosting the plugin instance + * 3) The plugin process + * + * If the plugin process crashes, we cannot be sure if the chrome process + * will hear about it first, or the content process will hear about it + * first. Because of how IPC works, that's really up to the operating system, + * and we assume any guarantees about it, so we have to account for both + * possibilities. + * + * This test exercises the browser's reaction to both possibilities. + */ + +const CRASH_URL = "http://example.com/browser/browser/base/content/test/plugins/plugin_crashCommentAndURL.html"; +const CRASHED_MESSAGE = "BrowserPlugins:NPAPIPluginProcessCrashed"; + +/** + * In order for our test to work, we need to be able to put a plugin + * in a very specific state. Specifically, we need it to match the + * :-moz-handler-crashed pseudoselector. The only way I can find to + * do that is by actually crashing the plugin. So we wait for the + * plugin to crash and show the "please" state (since that will + * only show if both the message from the parent has been received + * AND the PluginCrashed event has fired). + * + * Once in that state, we try to rewind the clock a little bit - we clear + * out the crashData cache in the PluginContent with a message, and we also + * override the pluginFallbackState of the <object> to fool PluginContent + * into believing that the plugin is in a particular state. + * + * @param browser + * The browser that has loaded the CRASH_URL that we need to + * prepare to be in the special state. + * @param pluginFallbackState + * The value we should override the <object>'s pluginFallbackState + * with. + * @return Promise + * The Promise resolves when the plugin has officially been put into + * the crash reporter state, and then "rewound" to have the "status" + * attribute of the statusDiv removed. The resolved Promise returns + * the run ID for the crashed plugin. It rejects if we never get into + * the crash reporter state. + */ +function preparePlugin(browser, pluginFallbackState) { + return ContentTask.spawn(browser, pluginFallbackState, function* (pluginFallbackState) { + let plugin = content.document.getElementById("plugin"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + // CRASH_URL will load a plugin that crashes immediately. We + // wait until the plugin has finished being put into the crash + // state. + let statusDiv; + yield ContentTaskUtils.waitForCondition(() => { + statusDiv = plugin.ownerDocument + .getAnonymousElementByAttribute(plugin, "anonid", + "submitStatus"); + return statusDiv && statusDiv.getAttribute("status") == "please"; + }, "Timed out waiting for plugin to be in crash report state"); + + // "Rewind", by wiping out the status attribute... + statusDiv.removeAttribute("status"); + // Somehow, I'm able to get away with overriding the getter for + // this XPCOM object. Probably because I've got chrome privledges. + Object.defineProperty(plugin, "pluginFallbackType", { + get: function() { + return pluginFallbackState; + } + }); + return plugin.runID; + }).then((runID) => { + browser.messageManager.sendAsyncMessage("BrowserPlugins:Test:ClearCrashData"); + return runID; + }); +} + +add_task(function* setup() { + // Bypass click-to-play + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED); + + // Clear out any minidumps we create from plugins - we really don't care + // about them. + let crashObserver = (subject, topic, data) => { + if (topic != "plugin-crashed") { + return; + } + + let propBag = subject.QueryInterface(Ci.nsIPropertyBag2); + let minidumpID = propBag.getPropertyAsAString("pluginDumpID"); + + let minidumpDir = Services.dirsvc.get("ProfD", Ci.nsIFile); + minidumpDir.append("minidumps"); + + let pluginDumpFile = minidumpDir.clone(); + pluginDumpFile.append(minidumpID + ".dmp"); + + let extraFile = minidumpDir.clone(); + extraFile.append(minidumpID + ".extra"); + + ok(pluginDumpFile.exists(), "Found minidump"); + ok(extraFile.exists(), "Found extra file"); + + pluginDumpFile.remove(false); + extraFile.remove(false); + }; + + Services.obs.addObserver(crashObserver, "plugin-crashed", false); + // plugins.testmode will make BrowserPlugins:Test:ClearCrashData work. + Services.prefs.setBoolPref("plugins.testmode", true); + registerCleanupFunction(() => { + Services.prefs.clearUserPref("plugins.testmode"); + Services.obs.removeObserver(crashObserver, "plugin-crashed"); + }); +}); + +/** + * In this case, the chrome process hears about the crash first. + */ +add_task(function* testChromeHearsPluginCrashFirst() { + // Open a remote window so that we can run this test even if e10s is not + // enabled by default. + let win = yield BrowserTestUtils.openNewBrowserWindow({remote: true}); + let browser = win.gBrowser.selectedBrowser; + + browser.loadURI(CRASH_URL); + yield BrowserTestUtils.browserLoaded(browser); + + // In this case, we want the <object> to match the -moz-handler-crashed + // pseudoselector, but we want it to seem still active, because the + // content process is not yet supposed to know that the plugin has + // crashed. + let runID = yield preparePlugin(browser, + Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE); + + // Send the message down to PluginContent.jsm saying that the plugin has + // crashed, and that we have a crash report. + let mm = browser.messageManager; + mm.sendAsyncMessage(CRASHED_MESSAGE, + { pluginName: "", runID, state: "please" }); + + yield ContentTask.spawn(browser, null, function* () { + // At this point, the content process should have heard the + // plugin crash message from the parent, and we are OK to emit + // the PluginCrashed event. + let plugin = content.document.getElementById("plugin"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + let statusDiv = plugin.ownerDocument + .getAnonymousElementByAttribute(plugin, "anonid", + "submitStatus"); + + if (statusDiv.getAttribute("status") == "please") { + Assert.ok(false, "Did not expect plugin to be in crash report mode yet."); + return; + } + + // Now we need the plugin to seem crashed to PluginContent.jsm, without + // actually crashing the plugin again. We hack around this by overriding + // the pluginFallbackType again. + Object.defineProperty(plugin, "pluginFallbackType", { + get: function() { + return Ci.nsIObjectLoadingContent.PLUGIN_CRASHED; + }, + }); + + let event = new content.PluginCrashedEvent("PluginCrashed", { + pluginName: "", + pluginDumpID: "", + browserDumpID: "", + submittedCrashReport: false, + bubbles: true, + cancelable: true, + }); + + plugin.dispatchEvent(event); + Assert.equal(statusDiv.getAttribute("status"), "please", + "Should have been showing crash report UI"); + }); + yield BrowserTestUtils.closeWindow(win); +}); + +/** + * In this case, the content process hears about the crash first. + */ +add_task(function* testContentHearsCrashFirst() { + // Open a remote window so that we can run this test even if e10s is not + // enabled by default. + let win = yield BrowserTestUtils.openNewBrowserWindow({remote: true}); + let browser = win.gBrowser.selectedBrowser; + + browser.loadURI(CRASH_URL); + yield BrowserTestUtils.browserLoaded(browser); + + // In this case, we want the <object> to match the -moz-handler-crashed + // pseudoselector, and we want the plugin to seem crashed, since the + // content process in this case has heard about the crash first. + let runID = yield preparePlugin(browser, + Ci.nsIObjectLoadingContent.PLUGIN_CRASHED); + + yield ContentTask.spawn(browser, null, function* () { + // At this point, the content process has not yet heard from the + // parent about the crash report. Let's ensure that by making sure + // we're not showing the plugin crash report UI. + let plugin = content.document.getElementById("plugin"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + let statusDiv = plugin.ownerDocument + .getAnonymousElementByAttribute(plugin, "anonid", + "submitStatus"); + + if (statusDiv.getAttribute("status") == "please") { + Assert.ok(false, "Did not expect plugin to be in crash report mode yet."); + } + + let event = new content.PluginCrashedEvent("PluginCrashed", { + pluginName: "", + pluginDumpID: "", + browserDumpID: "", + submittedCrashReport: false, + bubbles: true, + cancelable: true, + }); + + plugin.dispatchEvent(event); + + Assert.notEqual(statusDiv.getAttribute("status"), "please", + "Should not yet be showing crash report UI"); + }); + + // Now send the message down to PluginContent.jsm that the plugin has + // crashed... + let mm = browser.messageManager; + mm.sendAsyncMessage(CRASHED_MESSAGE, + { pluginName: "", runID, state: "please"}); + + yield ContentTask.spawn(browser, null, function* () { + // At this point, the content process will have heard the message + // from the parent and reacted to it. We should be showing the plugin + // crash report UI now. + let plugin = content.document.getElementById("plugin"); + plugin.QueryInterface(Ci.nsIObjectLoadingContent); + let statusDiv = plugin.ownerDocument + .getAnonymousElementByAttribute(plugin, "anonid", + "submitStatus"); + + Assert.equal(statusDiv.getAttribute("status"), "please", + "Should have been showing crash report UI"); + }); + + yield BrowserTestUtils.closeWindow(win); +}); diff --git a/browser/base/content/test/plugins/browser_plugin_reloading.js b/browser/base/content/test/plugins/browser_plugin_reloading.js new file mode 100644 index 000000000..7327d4cf9 --- /dev/null +++ b/browser/base/content/test/plugins/browser_plugin_reloading.js @@ -0,0 +1,85 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); +var gTestBrowser = null; + +function updateAllTestPlugins(aState) { + setTestPluginEnabledState(aState, "Test Plug-in"); + setTestPluginEnabledState(aState, "Second Test Plug-in"); +} + +add_task(function* () { + registerCleanupFunction(Task.async(function*() { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + resetBlocklist(); + gTestBrowser = null; + gBrowser.removeCurrentTab(); + window.focus(); + })); +}); + +add_task(function* () { + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + // Prime the blocklist service, the remote service doesn't launch on startup. + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html></html>"); + let exmsg = yield promiseInitContentBlocklistSvc(gBrowser.selectedBrowser); + ok(!exmsg, "exception: " + exmsg); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); +}); + +// Tests that a click-to-play plugin retains its activated state upon reloading +add_task(function* () { + clearAllPluginPermissions(); + + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 1, Should have a click-to-play notification"); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, + "Test 2, plugin fallback type should be PLUGIN_CLICK_TO_PLAY"); + + // run the plugin + yield promisePlayObject("test"); + + yield promiseUpdatePluginBindings(gTestBrowser); + + pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 3, plugin should have started"); + ok(pluginInfo.activated, "Test 4, plugin node should not be activated"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let plugin = content.document.getElementById("test"); + let npobj1 = Components.utils.waiveXrays(plugin).getObjectValue(); + plugin.src = plugin.src; + let pluginsDiffer = false; + try { + Components.utils.waiveXrays(plugin).checkObjectValue(npobj1); + } catch (e) { + pluginsDiffer = true; + } + + Assert.ok(pluginsDiffer, "Test 5, plugins differ."); + }); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 6, Plugin should have retained activated state."); + is(pluginInfo.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 7, plugin should have started"); +}); diff --git a/browser/base/content/test/plugins/browser_pluginnotification.js b/browser/base/content/test/plugins/browser_pluginnotification.js new file mode 100644 index 000000000..bf32f37a4 --- /dev/null +++ b/browser/base/content/test/plugins/browser_pluginnotification.js @@ -0,0 +1,626 @@ +var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); +var gTestBrowser = null; + +function updateAllTestPlugins(aState) { + setTestPluginEnabledState(aState, "Test Plug-in"); + setTestPluginEnabledState(aState, "Second Test Plug-in"); +} + +add_task(function* () { + registerCleanupFunction(Task.async(function*() { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + resetBlocklist(); + gTestBrowser = null; + gBrowser.removeCurrentTab(); + window.focus(); + })); +}); + +add_task(function* () { + gBrowser.selectedTab = gBrowser.addTab(); + gTestBrowser = gBrowser.selectedBrowser; + + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + // Prime the blocklist service, the remote service doesn't launch on startup. + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html></html>"); + let exmsg = yield promiseInitContentBlocklistSvc(gBrowser.selectedBrowser); + ok(!exmsg, "exception: " + exmsg); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); +}); + +// Tests a page with an unknown plugin in it. +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_unknown.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let pluginInfo = yield promiseForPluginInfo("unknown"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED, + "Test 1a, plugin fallback type should be PLUGIN_UNSUPPORTED"); +}); + +// Test that the doorhanger is shown when the user clicks on the overlay +// after having previously blocked the plugin. +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Plugin should not be activated"); + + // Simulate clicking the "Allow Now" button. + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + + yield promiseForNotificationShown(notification); + + PopupNotifications.panel.firstChild._secondaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Plugin should be activated"); + + // Simulate clicking the "Block" button. + yield promiseForNotificationShown(notification); + + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Plugin should not be activated"); + + // Simulate clicking the overlay + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let bounds = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + + ok(!notification.dismissed, "A plugin notification should be shown."); + + clearAllPluginPermissions(); +}); + +// Tests that going back will reshow the notification for click-to-play plugins +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html>hi</html>"); + + // make sure the notification is gone + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!notification, "Test 11b, Should not have a click-to-play notification"); + + gTestBrowser.webNavigation.goBack(); + + yield promisePopupNotification("click-to-play-plugins"); +}); + +// Tests that the "Allow Always" permission works for click-to-play plugins +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 12a, Plugin should not be activated"); + + // Simulate clicking the "Allow Always" button. + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + + yield promiseForNotificationShown(notification); + + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 12a, Plugin should be activated"); +}); + +// Test that the "Always" permission, when set for just the Test plugin, +// does not also allow the Second Test plugin. +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_two_types.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + yield promisePopupNotification("click-to-play-plugins"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let test = content.document.getElementById("test"); + let secondtestA = content.document.getElementById("secondtestA"); + let secondtestB = content.document.getElementById("secondtestB"); + Assert.ok(test.activated && !secondtestA.activated && !secondtestB.activated, + "Content plugins are set up"); + }); + + clearAllPluginPermissions(); +}); + +// Tests that the plugin's "activated" property is true for working plugins +// with click-to-play disabled. +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_ENABLED); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test2.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let pluginInfo = yield promiseForPluginInfo("test1"); + ok(pluginInfo.activated, "Test 14, Plugin should be activated"); +}); + +// Tests that the overlay is shown instead of alternate content when +// plugins are click to play. +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_alternate_content.html"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let mainBox = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(!!mainBox, "Test 15, Plugin overlay should exist"); + }); +}); + +// Tests that mContentType is used for click-to-play plugins, and not the +// inspected type. +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_bug749455.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 17, Should have a click-to-play notification"); +}); + +// Tests that clicking the icon of the overlay activates the doorhanger +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 18g, Plugin should not be activated"); + + ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, + "Test 19a, Doorhanger should start out dismissed"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let icon = doc.getAnonymousElementByAttribute(plugin, "class", "icon"); + let bounds = icon.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + + let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed; + yield promiseForCondition(condition); +}); + +// Tests that clicking the text of the overlay activates the plugin +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 18g, Plugin should not be activated"); + + ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, + "Test 19c, Doorhanger should start out dismissed"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let text = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay"); + let bounds = text.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + + let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed; + yield promiseForCondition(condition); +}); + +// Tests that clicking the box of the overlay activates the doorhanger +// (just to be thorough) +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 18g, Plugin should not be activated"); + + ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed, + "Test 19e, Doorhanger should start out dismissed"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", 50, 50, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", 50, 50, 0, 1, 0, false, 0, 0); + }); + + let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed && + PopupNotifications.panel.firstChild; + yield promiseForCondition(condition); + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 19e, Plugin should not be activated"); + + clearAllPluginPermissions(); +}); + +// Tests that a plugin in a div that goes from style="display: none" to +// "display: block" can be clicked to activate. +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_hidden_to_visible.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 20a, Should have a click-to-play notification"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + Assert.ok(!!overlay, "Test 20a, Plugin overlay should exist"); + }); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let mainBox = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + let overlayRect = mainBox.getBoundingClientRect(); + Assert.ok(overlayRect.width == 0 && overlayRect.height == 0, + "Test 20a, plugin should have an overlay with 0px width and height"); + }); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 20b, plugin should not be activated"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let div = doc.getElementById("container"); + Assert.equal(div.style.display, "none", + "Test 20b, container div should be display: none"); + }); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let div = doc.getElementById("container"); + div.style.display = "block"; + }); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let mainBox = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); + let overlayRect = mainBox.getBoundingClientRect(); + Assert.ok(overlayRect.width == 200 && overlayRect.height == 200, + "Test 20c, plugin should have overlay dims of 200px"); + }); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(!pluginInfo.activated, "Test 20b, plugin should not be activated"); + + ok(notification.dismissed, "Test 20c, Doorhanger should start out dismissed"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let bounds = plugin.getBoundingClientRect(); + let left = (bounds.left + bounds.right) / 2; + let top = (bounds.top + bounds.bottom) / 2; + let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + }); + + let condition = () => !notification.dismissed && !!PopupNotifications.panel.firstChild; + yield promiseForCondition(condition); + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 20c, plugin should be activated"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect(); + Assert.ok(overlayRect.width == 0 && overlayRect.height == 0, + "Test 20c, plugin should have overlay dims of 0px"); + }); + + clearAllPluginPermissions(); +}); + +// Test having multiple different types of plugin on one page +add_task(function* () { + // contains three plugins, application/x-test, application/x-second-test x 2 + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_two_types.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 21a, Should have a click-to-play notification"); + + // confirm all three are blocked by ctp at this point + let ids = ["test", "secondtestA", "secondtestB"]; + for (let id of ids) { + yield ContentTask.spawn(gTestBrowser, { id }, function* (args) { + let doc = content.document; + let plugin = doc.getElementById(args.id); + let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect(); + Assert.ok(overlayRect.width == 200 && overlayRect.height == 200, + "Test 21a, plugin " + args.id + " should have click-to-play overlay with dims"); + }); + + let pluginInfo = yield promiseForPluginInfo(id); + ok(!pluginInfo.activated, "Test 21a, Plugin with id=" + id + " should not be activated"); + } + + notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 21a, Should have a click-to-play notification"); + + // we have to actually show the panel to get the bindings to instantiate + yield promiseForNotificationShown(notification); + + is(notification.options.pluginData.size, 2, "Test 21a, Should have two types of plugin in the notification"); + + let centerAction = null; + for (let action of notification.options.pluginData.values()) { + if (action.pluginName == "Test") { + centerAction = action; + break; + } + } + ok(centerAction, "Test 21b, found center action for the Test plugin"); + + let centerItem = null; + for (let item of PopupNotifications.panel.firstChild.childNodes) { + is(item.value, "block", "Test 21b, all plugins should start out blocked"); + if (item.action == centerAction) { + centerItem = item; + break; + } + } + ok(centerItem, "Test 21b, found center item for the Test plugin"); + + // Select the allow now option in the select drop down for Test Plugin + centerItem.value = "allownow"; + + // "click" the button to activate the Test plugin + PopupNotifications.panel.firstChild._primaryButton.click(); + + let pluginInfo = yield promiseForPluginInfo("test"); + ok(pluginInfo.activated, "Test 21b, plugin should be activated"); + + notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 21b, Should have a click-to-play notification"); + + yield promiseForNotificationShown(notification); + + ok(notification.options.pluginData.size == 2, "Test 21c, Should have one type of plugin in the notification"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect(); + Assert.ok(overlayRect.width == 0 && overlayRect.height == 0, + "Test 21c, plugin should have overlay dims of 0px"); + }); + + ids = ["secondtestA", "secondtestB"]; + for (let id of ids) { + yield ContentTask.spawn(gTestBrowser, { id }, function* (args) { + let doc = content.document; + let plugin = doc.getElementById(args.id); + let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect(); + Assert.ok(overlayRect.width == 200 && overlayRect.height == 200, + "Test 21c, plugin " + args.id + " should have click-to-play overlay with zero dims"); + }); + + + let pluginInfo = yield promiseForPluginInfo(id); + ok(!pluginInfo.activated, "Test 21c, Plugin with id=" + id + " should not be activated"); + } + + centerAction = null; + for (let action of notification.options.pluginData.values()) { + if (action.pluginName == "Second Test") { + centerAction = action; + break; + } + } + ok(centerAction, "Test 21d, found center action for the Second Test plugin"); + + centerItem = null; + for (let item of PopupNotifications.panel.firstChild.childNodes) { + if (item.action == centerAction) { + is(item.value, "block", "Test 21d, test plugin 2 should start blocked"); + centerItem = item; + break; + } + else { + is(item.value, "allownow", "Test 21d, test plugin should be enabled"); + } + } + ok(centerItem, "Test 21d, found center item for the Second Test plugin"); + + // Select the allow now option in the select drop down for Second Test Plguins + centerItem.value = "allownow"; + + // "click" the button to activate the Second Test plugins + PopupNotifications.panel.firstChild._primaryButton.click(); + + notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 21d, Should have a click-to-play notification"); + + ids = ["test", "secondtestA", "secondtestB"]; + for (let id of ids) { + yield ContentTask.spawn(gTestBrowser, { id }, function* (args) { + let doc = content.document; + let plugin = doc.getElementById(args.id); + let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect(); + Assert.ok(overlayRect.width == 0 && overlayRect.height == 0, + "Test 21d, plugin " + args.id + " should have click-to-play overlay with zero dims"); + }); + + let pluginInfo = yield promiseForPluginInfo(id); + ok(pluginInfo.activated, "Test 21d, Plugin with id=" + id + " should not be activated"); + } +}); + +// Tests that a click-to-play plugin resets its activated state when changing types +add_task(function* () { + clearAllPluginPermissions(); + + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 22, Should have a click-to-play notification"); + + // Plugin should start as CTP + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, + "Test 23, plugin fallback type should be PLUGIN_CLICK_TO_PLAY"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + plugin.type = null; + // We currently don't properly change state just on type change, + // so rebind the plugin to tree. bug 767631 + plugin.parentNode.appendChild(plugin); + }); + + pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, plugin should be TYPE_NULL"); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let doc = content.document; + let plugin = doc.getElementById("test"); + plugin.type = "application/x-test"; + plugin.parentNode.appendChild(plugin); + }); + + pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.displayedType, Ci.nsIObjectLoadingContent.TYPE_NULL, "Test 23, plugin should be TYPE_NULL"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, + "Test 23, plugin fallback type should be PLUGIN_CLICK_TO_PLAY"); + ok(!pluginInfo.activated, "Test 23, plugin node should not be activated"); +}); + +// Plugin sync removal test. Note this test produces a notification drop down since +// the plugin we add has zero dims. +add_task(function* () { + updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_syncRemoved.html"); + + // Maybe there some better trick here, we need to wait for the page load, then + // wait for the js to execute in the page. + yield waitForMs(500); + + let notification = PopupNotifications.getNotification("click-to-play-plugins"); + ok(notification, "Test 25: There should be a plugin notification even if the plugin was immediately removed"); + ok(notification.dismissed, "Test 25: The notification should be dismissed by default"); + + yield promiseTabLoadEvent(gBrowser.selectedTab, "data:text/html,<html>hi</html>"); +}); + +// Tests a page with a blocked plugin in it and make sure the infoURL property +// the blocklist file gets used. +add_task(function* () { + clearAllPluginPermissions(); + + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginInfoURL.xml", gTestBrowser); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html"); + + // Work around for delayed PluginBindingAttached + yield promiseUpdatePluginBindings(gTestBrowser); + + let notification = PopupNotifications.getNotification("click-to-play-plugins"); + + // Since the plugin notification is dismissed by default, reshow it. + yield promiseForNotificationShown(notification); + + let pluginInfo = yield promiseForPluginInfo("test"); + is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, + "Test 26, plugin fallback type should be PLUGIN_BLOCKLISTED"); + ok(!pluginInfo.activated, "Plugin should be activated."); + + const testUrl = "http://test.url.com/"; + + let firstPanelChild = PopupNotifications.panel.firstChild; + let infoLink = document.getAnonymousElementByAttribute(firstPanelChild, "anonid", + "click-to-play-plugins-notification-link"); + is(infoLink.href, testUrl, + "Test 26, the notification URL needs to match the infoURL from the blocklist file."); +}); diff --git a/browser/base/content/test/plugins/browser_plugins_added_dynamically.js b/browser/base/content/test/plugins/browser_plugins_added_dynamically.js new file mode 100644 index 000000000..22077a54d --- /dev/null +++ b/browser/base/content/test/plugins/browser_plugins_added_dynamically.js @@ -0,0 +1,137 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://mochi.test:8888/"); +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + +var gTestBrowser = null; + +add_task(function* () { + registerCleanupFunction(Task.async(function*() { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("plugins.click_to_play"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in"); + yield asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser); + resetBlocklist(); + gBrowser.removeCurrentTab(); + window.focus(); + gTestBrowser = null; + })); +}); + +// "Activate" of a given type -> plugins of that type dynamically added should +// automatically play. +add_task(function* () { + let newTab = gBrowser.addTab(); + gBrowser.selectedTab = newTab; + gTestBrowser = gBrowser.selectedBrowser; + + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); + setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in"); +}); + +add_task(function* () { + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_add_dynamically.html"); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!notification, "Test 1a, Should not have a click-to-play notification"); + + // Add a plugin of type test + yield ContentTask.spawn(gTestBrowser, {}, function* () { + new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin("pluginone", "application/x-test")); + }); + + yield promisePopupNotification("click-to-play-plugins"); + + notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 1a, Should not have a click-to-play notification"); + + yield promiseForNotificationShown(notification); + + let centerAction = null; + for (let action of notification.options.pluginData.values()) { + if (action.pluginName == "Test") { + centerAction = action; + break; + } + } + ok(centerAction, "Test 2, found center action for the Test plugin"); + + let centerItem = null; + for (let item of PopupNotifications.panel.firstChild.childNodes) { + is(item.value, "block", "Test 3, all plugins should start out blocked"); + if (item.action == centerAction) { + centerItem = item; + break; + } + } + ok(centerItem, "Test 4, found center item for the Test plugin"); + + // Select the allow now option in the select drop down for Test Plugin + centerItem.value = "allownow"; + + // "click" the button to activate the Test plugin + PopupNotifications.panel.firstChild._primaryButton.click(); + + let pluginInfo = yield promiseForPluginInfo("pluginone"); + ok(pluginInfo.activated, "Test 5, plugin should be activated"); + + // Add another plugin of type test + yield ContentTask.spawn(gTestBrowser, {}, function* () { + new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin("plugintwo", "application/x-test")); + }); + + pluginInfo = yield promiseForPluginInfo("plugintwo"); + ok(pluginInfo.activated, "Test 6, plugins should be activated"); +}); + +// "Activate" of a given type -> plugins of other types dynamically added +// should not automatically play. +add_task(function* () { + clearAllPluginPermissions(); + + yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_add_dynamically.html"); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!notification, "Test 7, Should not have a click-to-play notification"); + + // Add a plugin of type test + yield ContentTask.spawn(gTestBrowser, {}, function* () { + new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin("pluginone", "application/x-test")); + }); + + yield promisePopupNotification("click-to-play-plugins"); + + notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 8, Should not have a click-to-play notification"); + + yield promiseForNotificationShown(notification); + + is(notification.options.pluginData.size, 1, "Should be one plugin action"); + + let pluginInfo = yield promiseForPluginInfo("pluginone"); + ok(!pluginInfo.activated, "Test 8, test plugin should be activated"); + + let condition = () => !notification.dismissed && + PopupNotifications.panel.firstChild; + yield promiseForCondition(condition); + + // "click" the button to activate the Test plugin + PopupNotifications.panel.firstChild._primaryButton.click(); + + pluginInfo = yield promiseForPluginInfo("pluginone"); + ok(pluginInfo.activated, "Test 9, test plugin should be activated"); + + yield ContentTask.spawn(gTestBrowser, {}, function* () { + new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin("plugintwo", "application/x-second-test")); + }); + + yield promisePopupNotification("click-to-play-plugins"); + + pluginInfo = yield promiseForPluginInfo("pluginone"); + ok(pluginInfo.activated, "Test 10, plugins should be activated"); + pluginInfo = yield promiseForPluginInfo("plugintwo"); + ok(!pluginInfo.activated, "Test 11, plugins should be activated"); +}); diff --git a/browser/base/content/test/plugins/browser_private_clicktoplay.js b/browser/base/content/test/plugins/browser_private_clicktoplay.js new file mode 100644 index 000000000..785b1bb31 --- /dev/null +++ b/browser/base/content/test/plugins/browser_private_clicktoplay.js @@ -0,0 +1,216 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir; +const gHttpTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); + +var gTestBrowser = null; +var gNextTest = null; +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + +Components.utils.import("resource://gre/modules/Services.jsm"); + +var gPrivateWindow = null; +var gPrivateBrowser = null; + +function finishTest() { + clearAllPluginPermissions(); + gBrowser.removeCurrentTab(); + if (gPrivateWindow) { + gPrivateWindow.close(); + } + window.focus(); +} + +let createPrivateWindow = Task.async(function* createPrivateWindow(url) { + gPrivateWindow = yield BrowserTestUtils.openNewBrowserWindow({private: true}); + ok(!!gPrivateWindow, "should have created a private window."); + gPrivateBrowser = gPrivateWindow.getBrowser().selectedBrowser; + + BrowserTestUtils.loadURI(gPrivateBrowser, url); + yield BrowserTestUtils.browserLoaded(gPrivateBrowser); +}); + +add_task(function* test() { + registerCleanupFunction(function() { + clearAllPluginPermissions(); + getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_ENABLED; + getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_ENABLED; + }); + + let newTab = gBrowser.addTab(); + gBrowser.selectedTab = newTab; + gTestBrowser = gBrowser.selectedBrowser; + let promise = BrowserTestUtils.browserLoaded(gTestBrowser); + + Services.prefs.setBoolPref("plugins.click_to_play", true); + getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY; + getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY; + yield promise; +}); + +add_task(function* test1a() { + yield createPrivateWindow(gHttpTestRoot + "plugin_test.html"); +}); + +add_task(function* test1b() { + let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser); + ok(popupNotification, "Test 1b, Should have a click-to-play notification"); + + yield ContentTask.spawn(gPrivateBrowser, null, function() { + let plugin = content.document.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(!objLoadingContent.activated, "Test 1b, Plugin should not be activated"); + }); + + // Check the button status + let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel, + "Shown"); + popupNotification.reshow(); + + yield promiseShown; + let button1 = gPrivateWindow.PopupNotifications.panel.firstChild._primaryButton; + let button2 = gPrivateWindow.PopupNotifications.panel.firstChild._secondaryButton; + is(button1.getAttribute("action"), "_singleActivateNow", "Test 1b, Blocked plugin in private window should have a activate now button"); + ok(button2.hidden, "Test 1b, Blocked plugin in a private window should not have a secondary button") + + gPrivateWindow.close(); + BrowserTestUtils.loadURI(gTestBrowser, gHttpTestRoot + "plugin_test.html"); + yield BrowserTestUtils.browserLoaded(gTestBrowser); +}); + +add_task(function* test2a() { + // enable test plugin on this site + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "Test 2a, Should have a click-to-play notification"); + + yield ContentTask.spawn(gTestBrowser, null, function() { + let plugin = content.document.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(!objLoadingContent.activated, "Test 2a, Plugin should not be activated"); + }); + + // Simulate clicking the "Allow Now" button. + let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel, + "Shown"); + popupNotification.reshow(); + yield promiseShown; + + PopupNotifications.panel.firstChild._secondaryButton.click(); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let plugin = content.document.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + let condition = () => objLoadingContent.activated; + yield ContentTaskUtils.waitForCondition(condition, "Test 2a, Waited too long for plugin to activate"); + }); +}); + +add_task(function* test2c() { + let topicObserved = TestUtils.topicObserved("PopupNotifications-updateNotShowing"); + yield createPrivateWindow(gHttpTestRoot + "plugin_test.html"); + yield topicObserved; + + let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser); + ok(popupNotification, "Test 2c, Should have a click-to-play notification"); + + yield ContentTask.spawn(gPrivateBrowser, null, function() { + let plugin = content.document.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(objLoadingContent.activated, "Test 2c, Plugin should be activated"); + }); + + // Check the button status + let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel, + "Shown"); + popupNotification.reshow(); + yield promiseShown; + let buttonContainer = gPrivateWindow.PopupNotifications.panel.firstChild._buttonContainer; + ok(buttonContainer.hidden, "Test 2c, Activated plugin in a private window should not have visible buttons"); + + clearAllPluginPermissions(); + gPrivateWindow.close(); + + BrowserTestUtils.loadURI(gTestBrowser, gHttpTestRoot + "plugin_test.html"); + yield BrowserTestUtils.browserLoaded(gTestBrowser); +}); + +add_task(function* test3a() { + // enable test plugin on this site + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "Test 3a, Should have a click-to-play notification"); + + yield ContentTask.spawn(gTestBrowser, null, function() { + let plugin = content.document.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(!objLoadingContent.activated, "Test 3a, Plugin should not be activated"); + }); + + // Simulate clicking the "Allow Always" button. + let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel, + "Shown"); + popupNotification.reshow(); + yield promiseShown; + PopupNotifications.panel.firstChild._secondaryButton.click(); + + yield ContentTask.spawn(gTestBrowser, null, function* () { + let plugin = content.document.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + let condition = () => objLoadingContent.activated; + yield ContentTaskUtils.waitForCondition(condition, "Test 3a, Waited too long for plugin to activate"); + }); +}); + +add_task(function* test3c() { + let topicObserved = TestUtils.topicObserved("PopupNotifications-updateNotShowing"); + yield createPrivateWindow(gHttpTestRoot + "plugin_test.html"); + yield topicObserved; + + let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser); + ok(popupNotification, "Test 3c, Should have a click-to-play notification"); + + // Check the button status + let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel, + "Shown"); + popupNotification.reshow(); + yield promiseShown; + let buttonContainer = gPrivateWindow.PopupNotifications.panel.firstChild._buttonContainer; + ok(buttonContainer.hidden, "Test 3c, Activated plugin in a private window should not have visible buttons"); + + BrowserTestUtils.loadURI(gPrivateBrowser, gHttpTestRoot + "plugin_two_types.html"); + yield BrowserTestUtils.browserLoaded(gPrivateBrowser); +}); + +add_task(function* test3d() { + let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser); + ok(popupNotification, "Test 3d, Should have a click-to-play notification"); + + // Check the list item status + let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel, + "Shown"); + popupNotification.reshow(); + yield promiseShown; + let doc = gPrivateWindow.document; + for (let item of gPrivateWindow.PopupNotifications.panel.firstChild.childNodes) { + let allowalways = doc.getAnonymousElementByAttribute(item, "anonid", "allowalways"); + ok(allowalways, "Test 3d, should have list item for allow always"); + let allownow = doc.getAnonymousElementByAttribute(item, "anonid", "allownow"); + ok(allownow, "Test 3d, should have list item for allow now"); + let block = doc.getAnonymousElementByAttribute(item, "anonid", "block"); + ok(block, "Test 3d, should have list item for block"); + + if (item.action.pluginName === "Test") { + is(item.value, "allowalways", "Test 3d, Plugin should bet set to 'allow always'"); + ok(!allowalways.hidden, "Test 3d, Plugin set to 'always allow' should have a visible 'always allow' action."); + ok(allownow.hidden, "Test 3d, Plugin set to 'always allow' should have an invisible 'allow now' action."); + ok(block.hidden, "Test 3d, Plugin set to 'always allow' should have an invisible 'block' action."); + } else if (item.action.pluginName === "Second Test") { + is(item.value, "block", "Test 3d, Second plugin should bet set to 'block'"); + ok(allowalways.hidden, "Test 3d, Plugin set to 'block' should have a visible 'always allow' action."); + ok(!allownow.hidden, "Test 3d, Plugin set to 'block' should have a visible 'allow now' action."); + ok(!block.hidden, "Test 3d, Plugin set to 'block' should have a visible 'block' action."); + } else { + ok(false, "Test 3d, Unexpected plugin '"+item.action.pluginName+"'"); + } + } + + finishTest(); +}); diff --git a/browser/base/content/test/plugins/head.js b/browser/base/content/test/plugins/head.js new file mode 100644 index 000000000..4995c4dc6 --- /dev/null +++ b/browser/base/content/test/plugins/head.js @@ -0,0 +1,396 @@ +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", + "resource://gre/modules/PlacesUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils", + "resource://gre/modules/PromiseUtils.jsm"); + +// The blocklist shim running in the content process does not initialize at +// start up, so it's not active until we load content that needs to do a +// check. This helper bypasses the delay to get the svc up and running +// immediately. Note, call this after remote content has loaded. +function promiseInitContentBlocklistSvc(aBrowser) +{ + return ContentTask.spawn(aBrowser, {}, function* () { + try { + Cc["@mozilla.org/extensions/blocklist;1"] + .getService(Ci.nsIBlocklistService); + } catch (ex) { + return ex.message; + } + return null; + }); +} + +/** + * Waits a specified number of miliseconds. + * + * Usage: + * let wait = yield waitForMs(2000); + * ok(wait, "2 seconds should now have elapsed"); + * + * @param aMs the number of miliseconds to wait for + * @returns a Promise that resolves to true after the time has elapsed + */ +function waitForMs(aMs) { + return new Promise((resolve) => { + setTimeout(done, aMs); + function done() { + resolve(true); + } + }); +} + +function waitForEvent(subject, eventName, checkFn, useCapture, useUntrusted) { + return new Promise((resolve, reject) => { + subject.addEventListener(eventName, function listener(event) { + try { + if (checkFn && !checkFn(event)) { + return; + } + subject.removeEventListener(eventName, listener, useCapture); + resolve(event); + } catch (ex) { + try { + subject.removeEventListener(eventName, listener, useCapture); + } catch (ex2) { + // Maybe the provided object does not support removeEventListener. + } + reject(ex); + } + }, useCapture, useUntrusted); + }); +} + + +/** + * Waits for a load (or custom) event to finish in a given tab. If provided + * load an uri into the tab. + * + * @param tab + * The tab to load into. + * @param [optional] url + * The url to load, or the current url. + * @return {Promise} resolved when the event is handled. + * @resolves to the received event + * @rejects if a valid load event is not received within a meaningful interval + */ +function promiseTabLoadEvent(tab, url) { + info("Wait tab event: load"); + + function handle(loadedUrl) { + if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) { + info(`Skipping spurious load event for ${loadedUrl}`); + return false; + } + + info("Tab event received: load"); + return true; + } + + let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle); + + if (url) + BrowserTestUtils.loadURI(tab.linkedBrowser, url); + + return loaded; +} + +function waitForCondition(condition, nextTest, errorMsg, aTries, aWait) { + let tries = 0; + let maxTries = aTries || 100; // 100 tries + let maxWait = aWait || 100; // 100 msec x 100 tries = ten seconds + let interval = setInterval(function() { + if (tries >= maxTries) { + ok(false, errorMsg); + moveOn(); + } + let conditionPassed; + try { + conditionPassed = condition(); + } catch (e) { + ok(false, e + "\n" + e.stack); + conditionPassed = false; + } + if (conditionPassed) { + moveOn(); + } + tries++; + }, maxWait); + let moveOn = function() { clearInterval(interval); nextTest(); }; +} + +// Waits for a conditional function defined by the caller to return true. +function promiseForCondition(aConditionFn, aMessage, aTries, aWait) { + return new Promise((resolve) => { + waitForCondition(aConditionFn, resolve, + (aMessage || "Condition didn't pass."), + aTries, aWait); + }); +} + +// Returns the chrome side nsIPluginTag for this plugin +function getTestPlugin(aName) { + let pluginName = aName || "Test Plug-in"; + let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); + let tags = ph.getPluginTags(); + + // Find the test plugin + for (let i = 0; i < tags.length; i++) { + if (tags[i].name == pluginName) + return tags[i]; + } + ok(false, "Unable to find plugin"); + return null; +} + +// Set the 'enabledState' on the nsIPluginTag stored in the main or chrome +// process. +function setTestPluginEnabledState(newEnabledState, pluginName) { + let name = pluginName || "Test Plug-in"; + let plugin = getTestPlugin(name); + plugin.enabledState = newEnabledState; +} + +// Get the 'enabledState' on the nsIPluginTag stored in the main or chrome +// process. +function getTestPluginEnabledState(pluginName) { + let name = pluginName || "Test Plug-in"; + let plugin = getTestPlugin(name); + return plugin.enabledState; +} + +// Returns a promise for nsIObjectLoadingContent props data. +function promiseForPluginInfo(aId, aBrowser) { + let browser = aBrowser || gTestBrowser; + return ContentTask.spawn(browser, aId, function* (aId) { + let plugin = content.document.getElementById(aId); + if (!(plugin instanceof Ci.nsIObjectLoadingContent)) + throw new Error("no plugin found"); + return { + pluginFallbackType: plugin.pluginFallbackType, + activated: plugin.activated, + hasRunningPlugin: plugin.hasRunningPlugin, + displayedType: plugin.displayedType, + }; + }); +} + +// Return a promise and call the plugin's nsIObjectLoadingContent +// playPlugin() method. +function promisePlayObject(aId, aBrowser) { + let browser = aBrowser || gTestBrowser; + return ContentTask.spawn(browser, aId, function* (aId) { + let plugin = content.document.getElementById(aId); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + objLoadingContent.playPlugin(); + }); +} + +function promiseCrashObject(aId, aBrowser) { + let browser = aBrowser || gTestBrowser; + return ContentTask.spawn(browser, aId, function* (aId) { + let plugin = content.document.getElementById(aId); + Components.utils.waiveXrays(plugin).crash(); + }); +} + +// Return a promise and call the plugin's getObjectValue() method. +function promiseObjectValueResult(aId, aBrowser) { + let browser = aBrowser || gTestBrowser; + return ContentTask.spawn(browser, aId, function* (aId) { + let plugin = content.document.getElementById(aId); + return Components.utils.waiveXrays(plugin).getObjectValue(); + }); +} + +// Return a promise and reload the target plugin in the page +function promiseReloadPlugin(aId, aBrowser) { + let browser = aBrowser || gTestBrowser; + return ContentTask.spawn(browser, aId, function* (aId) { + let plugin = content.document.getElementById(aId); + plugin.src = plugin.src; + }); +} + +// after a test is done using the plugin doorhanger, we should just clear +// any permissions that may have crept in +function clearAllPluginPermissions() { + let perms = Services.perms.enumerator; + while (perms.hasMoreElements()) { + let perm = perms.getNext(); + if (perm.type.startsWith('plugin')) { + info("removing permission:" + perm.principal.origin + " " + perm.type + "\n"); + Services.perms.removePermission(perm); + } + } +} + +function updateBlocklist(aCallback) { + let blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"] + .getService(Ci.nsITimerCallback); + let observer = function() { + Services.obs.removeObserver(observer, "blocklist-updated"); + SimpleTest.executeSoon(aCallback); + }; + Services.obs.addObserver(observer, "blocklist-updated", false); + blocklistNotifier.notify(null); +} + +var _originalTestBlocklistURL = null; +function setAndUpdateBlocklist(aURL, aCallback) { + if (!_originalTestBlocklistURL) { + _originalTestBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url"); + } + Services.prefs.setCharPref("extensions.blocklist.url", aURL); + updateBlocklist(aCallback); +} + +// A generator that insures a new blocklist is loaded (in both +// processes if applicable). +function* asyncSetAndUpdateBlocklist(aURL, aBrowser) { + info("*** loading new blocklist: " + aURL); + let doTestRemote = aBrowser ? aBrowser.isRemoteBrowser : false; + if (!_originalTestBlocklistURL) { + _originalTestBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url"); + } + Services.prefs.setCharPref("extensions.blocklist.url", aURL); + let localPromise = TestUtils.topicObserved("blocklist-updated"); + let remotePromise; + if (doTestRemote) { + remotePromise = TestUtils.topicObserved("content-blocklist-updated"); + } + let blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"] + .getService(Ci.nsITimerCallback); + blocklistNotifier.notify(null); + info("*** waiting on local load"); + yield localPromise; + if (doTestRemote) { + info("*** waiting on remote load"); + yield remotePromise; + } + info("*** blocklist loaded."); +} + +// Reset back to the blocklist we had at the start of the test run. +function resetBlocklist() { + Services.prefs.setCharPref("extensions.blocklist.url", _originalTestBlocklistURL); +} + +// Insure there's a popup notification present. This test does not indicate +// open state. aBrowser can be undefined. +function promisePopupNotification(aName, aBrowser) { + return new Promise((resolve) => { + waitForCondition(() => PopupNotifications.getNotification(aName, aBrowser), + () => { + ok(!!PopupNotifications.getNotification(aName, aBrowser), + aName + " notification appeared"); + + resolve(); + }, "timeout waiting for popup notification " + aName); + }); +} + +/** + * Allows setting focus on a window, and waiting for that window to achieve + * focus. + * + * @param aWindow + * The window to focus and wait for. + * + * @return {Promise} + * @resolves When the window is focused. + * @rejects Never. + */ +function promiseWaitForFocus(aWindow) { + return new Promise((resolve) => { + waitForFocus(resolve, aWindow); + }); +} + +/** + * Returns a Promise that resolves when a notification bar + * for a browser is shown. Alternatively, for old-style callers, + * can automatically call a callback before it resolves. + * + * @param notificationID + * The ID of the notification to look for. + * @param browser + * The browser to check for the notification bar. + * @param callback (optional) + * A function to be called just before the Promise resolves. + * + * @return Promise + */ +function waitForNotificationBar(notificationID, browser, callback) { + return new Promise((resolve, reject) => { + let notification; + let notificationBox = gBrowser.getNotificationBox(browser); + waitForCondition( + () => (notification = notificationBox.getNotificationWithValue(notificationID)), + () => { + ok(notification, `Successfully got the ${notificationID} notification bar`); + if (callback) { + callback(notification); + } + resolve(notification); + }, + `Waited too long for the ${notificationID} notification bar` + ); + }); +} + +function promiseForNotificationBar(notificationID, browser) { + return new Promise((resolve) => { + waitForNotificationBar(notificationID, browser, resolve); + }); +} + +/** + * Reshow a notification and call a callback when it is reshown. + * @param notification + * The notification to reshow + * @param callback + * A function to be called when the notification has been reshown + */ +function waitForNotificationShown(notification, callback) { + if (PopupNotifications.panel.state == "open") { + executeSoon(callback); + return; + } + PopupNotifications.panel.addEventListener("popupshown", function onShown(e) { + PopupNotifications.panel.removeEventListener("popupshown", onShown); + callback(); + }, false); + notification.reshow(); +} + +function promiseForNotificationShown(notification) { + return new Promise((resolve) => { + waitForNotificationShown(notification, resolve); + }); +} + +/** + * Due to layout being async, "PluginBindAttached" may trigger later. This + * returns a Promise that resolves once we've forced a layout flush, which + * triggers the PluginBindAttached event to fire. This trick only works if + * there is some sort of plugin in the page. + * @param browser + * The browser to force plugin bindings in. + * @return Promise + */ +function promiseUpdatePluginBindings(browser) { + return ContentTask.spawn(browser, {}, function* () { + let doc = content.document; + let elems = doc.getElementsByTagName('embed'); + if (!elems || elems.length < 1) { + elems = doc.getElementsByTagName('object'); + } + if (elems && elems.length > 0) { + elems[0].clientTop; + } + }); +} diff --git a/browser/base/content/test/plugins/plugin_add_dynamically.html b/browser/base/content/test/plugins/plugin_add_dynamically.html new file mode 100644 index 000000000..863d36e09 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_add_dynamically.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<script> +function addPlugin(aId, aType="application/x-test") { + var embed = document.createElement("embed"); + embed.setAttribute("id", aId); + embed.style.width = "200px"; + embed.style.height = "200px"; + embed.setAttribute("type", aType); + return document.body.appendChild(embed); +} +</script> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_alternate_content.html b/browser/base/content/test/plugins/plugin_alternate_content.html new file mode 100644 index 000000000..f8acc833c --- /dev/null +++ b/browser/base/content/test/plugins/plugin_alternate_content.html @@ -0,0 +1,9 @@ +<!-- bug 739575 --> +<html> +<head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> +</head> +<body> +<object id="test" type="application/x-test" style="height: 200px; width:200px"> +<p><a href="about:blank">you should not see this link when plugins are click-to-play</a></p> +</object> +</body></html> diff --git a/browser/base/content/test/plugins/plugin_big.html b/browser/base/content/test/plugins/plugin_big.html new file mode 100644 index 000000000..d11506176 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_big.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="test" style="width: 500px; height: 500px" type="application/x-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_both.html b/browser/base/content/test/plugins/plugin_both.html new file mode 100644 index 000000000..2335366dc --- /dev/null +++ b/browser/base/content/test/plugins/plugin_both.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown"> +<embed id="test" style="width: 100px; height: 100px" type="application/x-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_both2.html b/browser/base/content/test/plugins/plugin_both2.html new file mode 100644 index 000000000..ba605d6e8 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_both2.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head>
+<meta charset="utf-8">
+</head> +<body> +<embed id="test" style="width: 100px; height: 100px" type="application/x-test"> +<embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_bug744745.html b/browser/base/content/test/plugins/plugin_bug744745.html new file mode 100644 index 000000000..d0691c9c0 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_bug744745.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head><meta charset="utf-8"/></head> +<body> +<style> +.x { + opacity: 0 !important; +} +</style> +<object id="test" class="x" type="application/x-test" width=200 height=200></object> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_bug749455.html b/browser/base/content/test/plugins/plugin_bug749455.html new file mode 100644 index 000000000..831dc82f7 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_bug749455.html @@ -0,0 +1,8 @@ +<!-- bug 749455 --> +<html> +<head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> +</head> +<body> +<embed src="plugin_bug749455.html" type="application/x-test" width="100px" height="100px"></embed> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_bug787619.html b/browser/base/content/test/plugins/plugin_bug787619.html new file mode 100644 index 000000000..cb91116f0 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_bug787619.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head><meta charset="utf-8"/></head> +<body> + <a id="wrapper"> + <embed id="plugin" style="width: 200px; height: 200px" type="application/x-test"> + </a> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_bug797677.html b/browser/base/content/test/plugins/plugin_bug797677.html new file mode 100644 index 000000000..1545f3647 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_bug797677.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<html> +<head><meta charset="utf-8"/></head> +<body><embed id="plugin" type="9000"></embed></body> +</html> diff --git a/browser/base/content/test/plugins/plugin_bug820497.html b/browser/base/content/test/plugins/plugin_bug820497.html new file mode 100644 index 000000000..4884e9dbe --- /dev/null +++ b/browser/base/content/test/plugins/plugin_bug820497.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> +<head><meta charset="utf-8"/></head> +<body> +<object id="test" type="application/x-test" width=200 height=200></object> +<script> + function addSecondPlugin() { + var object = document.createElement("object"); + object.type = "application/x-second-test"; + object.width = 200; + object.height = 200; + object.id = "secondtest"; + document.body.appendChild(object); + } +</script> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_clickToPlayAllow.html b/browser/base/content/test/plugins/plugin_clickToPlayAllow.html new file mode 100644 index 000000000..3f5df1984 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_clickToPlayAllow.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head>
+<meta charset="utf-8">
+</head> +<body> +<embed id="test" style="width: 200px; height: 200px" type="application/x-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_clickToPlayDeny.html b/browser/base/content/test/plugins/plugin_clickToPlayDeny.html new file mode 100644 index 000000000..3f5df1984 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_clickToPlayDeny.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head>
+<meta charset="utf-8">
+</head> +<body> +<embed id="test" style="width: 200px; height: 200px" type="application/x-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_crashCommentAndURL.html b/browser/base/content/test/plugins/plugin_crashCommentAndURL.html new file mode 100644 index 000000000..711a19ed3 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_crashCommentAndURL.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <script type="text/javascript"> + function crash() { + var plugin = document.getElementById("plugin"); + var argStr = decodeURIComponent(window.location.search.substr(1)); + if (argStr) { + var args = JSON.parse(argStr); + for (var key in args) + plugin.setAttribute(key, args[key]); + } + try { + plugin.crash(); + } + catch (err) {} + } + </script> + </head> + <body onload="crash();"> + <embed id="plugin" type="application/x-test" + width="400" height="400" + drawmode="solid" color="FF00FFFF"> + </embed> + </body> +</html> diff --git a/browser/base/content/test/plugins/plugin_data_url.html b/browser/base/content/test/plugins/plugin_data_url.html new file mode 100644 index 000000000..77e101144 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_data_url.html @@ -0,0 +1,11 @@ +<html> +<body> + <a id="data-link-1" href='data:text/html,<embed id="test" style="width: 200px; height: 200px" type="application/x-test"/>'> + data: with one plugin + </a><br /> + <a id="data-link-2" href='data:text/html,<embed id="test1" style="width: 200px; height: 200px" type="application/x-test"/><embed id="test2" style="width: 200px; height: 200px" type="application/x-second-test"/>'> + data: with two plugins + </a><br /> + <object id="test" style="width: 200px; height: 200px" type="application/x-test"></object> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_hidden_to_visible.html b/browser/base/content/test/plugins/plugin_hidden_to_visible.html new file mode 100644 index 000000000..eeacc1874 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_hidden_to_visible.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> + <div id="container" style="display: none"> + <object id="test" type="application/x-test" style="width: 200px; height: 200px;"></object> + </div> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_iframe.html b/browser/base/content/test/plugins/plugin_iframe.html new file mode 100644 index 000000000..239c9a771 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_iframe.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<iframe id="frame" with="400" height="400" src="plugin_test.html"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_outsideScrollArea.html b/browser/base/content/test/plugins/plugin_outsideScrollArea.html new file mode 100644 index 000000000..c6ef50d5d --- /dev/null +++ b/browser/base/content/test/plugins/plugin_outsideScrollArea.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<style type="text/css"> +#container { + position: fixed; + top: 0; + bottom: 0; + width: 100%; + height: 100%; + background: blue; +} + +#test { + width: 400px; + height: 400px; + position: absolute; +} +</style> +</head> +<body> + <div id="container"></div> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_overlayed.html b/browser/base/content/test/plugins/plugin_overlayed.html new file mode 100644 index 000000000..11c127093 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_overlayed.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <style type="text/css"> + .absthing { + width: 400px; + height: 400px; + position: absolute; + left: 20px; + top: 20px; + } + #d1 { + z-index: 1; + } + #d2 { + z-index: 2; + background-color: rgba(0,0,255,0.5); + border: 1px solid red; + } + </style> +<body> + <div class="absthing" id="d1"> + <embed id="test" type="application/x-test"> + </div> + <div class="absthing" id="d2"> + <p>This is overlaying + </div> diff --git a/browser/base/content/test/plugins/plugin_positioned.html b/browser/base/content/test/plugins/plugin_positioned.html new file mode 100644 index 000000000..1bad7ee46 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_positioned.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <style type="text/css"> + #test { + position: absolute; + left: -1000px; + top: -1000px; + } + </style> +<body> + <embed id="test" type="application/x-test"> diff --git a/browser/base/content/test/plugins/plugin_small.html b/browser/base/content/test/plugins/plugin_small.html new file mode 100644 index 000000000..f37ee28c7 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_small.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="test" style="width: 10px; height: 10px" type="application/x-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_small_2.html b/browser/base/content/test/plugins/plugin_small_2.html new file mode 100644 index 000000000..ebc5ffe84 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_small_2.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="test" style="width: 10px; height: 10px" type="application/x-second-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_syncRemoved.html b/browser/base/content/test/plugins/plugin_syncRemoved.html new file mode 100644 index 000000000..d97787056 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_syncRemoved.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<body> +<script type="text/javascript"> + // create an embed, insert it in the doc and immediately remove it + var embed = document.createElement('embed'); + embed.setAttribute("id", "test"); + embed.setAttribute("type", "application/x-test"); + embed.setAttribute("style", "width: 0px; height: 0px;"); + document.body.appendChild(embed); + window.getComputedStyle(embed, null).top; + document.body.remove(embed); +</script> diff --git a/browser/base/content/test/plugins/plugin_test.html b/browser/base/content/test/plugins/plugin_test.html new file mode 100644 index 000000000..d4b5b6ca7 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_test.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="test" style="width: 200px; height: 200px" type="application/x-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_test2.html b/browser/base/content/test/plugins/plugin_test2.html new file mode 100644 index 000000000..95614c930 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_test2.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="test1" style="width: 200px; height: 200px" type="application/x-test"> +<embed id="test2" style="width: 200px; height: 200px" type="application/x-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_test3.html b/browser/base/content/test/plugins/plugin_test3.html new file mode 100644 index 000000000..215c02326 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_test3.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="test" style="width: 0px; height: 0px" type="application/x-test"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_two_types.html b/browser/base/content/test/plugins/plugin_two_types.html new file mode 100644 index 000000000..2359d2ec1 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_two_types.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head><meta charset="utf-8"/></head> +<body> +<embed id="test" style="width: 200px; height: 200px" type="application/x-test"/> +<embed id="secondtestA" style="width: 200px; height: 200px" type="application/x-second-test"/> +<embed id="secondtestB" style="width: 200px; height: 200px" type="application/x-second-test"/> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_unknown.html b/browser/base/content/test/plugins/plugin_unknown.html new file mode 100644 index 000000000..578f455cc --- /dev/null +++ b/browser/base/content/test/plugins/plugin_unknown.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown"> +</body> +</html> diff --git a/browser/base/content/test/plugins/plugin_zoom.html b/browser/base/content/test/plugins/plugin_zoom.html new file mode 100644 index 000000000..f9e598658 --- /dev/null +++ b/browser/base/content/test/plugins/plugin_zoom.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<!-- The odd width and height are here to trigger bug 972237. --> +<embed id="test" style="width: 99.789%; height: 99.123%" type="application/x-test"> +</body> +</html> |