summaryrefslogtreecommitdiffstats
path: root/dom/plugins/test/mochitest
diff options
context:
space:
mode:
Diffstat (limited to 'dom/plugins/test/mochitest')
-rw-r--r--dom/plugins/test/mochitest/.eslintrc.js9
-rw-r--r--dom/plugins/test/mochitest/307-xo-redirect.sjs6
-rw-r--r--dom/plugins/test/mochitest/block_all_plugins.html10
-rw-r--r--dom/plugins/test/mochitest/browser.ini17
-rw-r--r--dom/plugins/test/mochitest/browser_blockallplugins.js66
-rw-r--r--dom/plugins/test/mochitest/browser_bug1163570.js118
-rw-r--r--dom/plugins/test/mochitest/browser_pluginscroll.js417
-rw-r--r--dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js141
-rw-r--r--dom/plugins/test/mochitest/file_authident.js14
-rw-r--r--dom/plugins/test/mochitest/file_bug771202.html8
-rw-r--r--dom/plugins/test/mochitest/file_bug863792.html43
-rw-r--r--dom/plugins/test/mochitest/head.js147
-rw-r--r--dom/plugins/test/mochitest/large-pic.jpgbin0 -> 98570 bytes
-rw-r--r--dom/plugins/test/mochitest/loremipsum.txt11
-rw-r--r--dom/plugins/test/mochitest/loremipsum.xtest11
-rw-r--r--dom/plugins/test/mochitest/loremipsum.xtest^headers^1
-rw-r--r--dom/plugins/test/mochitest/loremipsum_file.txt11
-rw-r--r--dom/plugins/test/mochitest/loremipsum_nocache.txt11
-rw-r--r--dom/plugins/test/mochitest/loremipsum_nocache.txt^headers^1
-rw-r--r--dom/plugins/test/mochitest/mixed_case_mime.sjs8
-rw-r--r--dom/plugins/test/mochitest/mochitest.ini45
-rw-r--r--dom/plugins/test/mochitest/neverending.sjs16
-rw-r--r--dom/plugins/test/mochitest/npruntime_identifiers_subpage.html4
-rw-r--r--dom/plugins/test/mochitest/plugin-stream-referer.sjs12
-rw-r--r--dom/plugins/test/mochitest/plugin-utils.js147
-rw-r--r--dom/plugins/test/mochitest/plugin_no_scroll_div.html10
-rw-r--r--dom/plugins/test/mochitest/plugin_subframe_test.html10
-rw-r--r--dom/plugins/test/mochitest/plugin_test.html16
-rw-r--r--dom/plugins/test/mochitest/plugin_window.html23
-rw-r--r--dom/plugins/test/mochitest/pluginstream.js46
-rw-r--r--dom/plugins/test/mochitest/post.sjs17
-rw-r--r--dom/plugins/test/mochitest/test_hanging.html59
-rw-r--r--dom/plugins/test/mochitest/test_mixed_case_mime.html25
-rw-r--r--dom/plugins/test/mochitest/test_plugin_fallback_focus.html80
-rw-r--r--dom/plugins/test/mochitest/test_plugin_scroll_invalidation.html109
-rw-r--r--dom/plugins/test/mochitest/test_plugin_scroll_painting.html64
-rw-r--r--dom/plugins/test/mochitest/test_pluginstream_geturl.html31
-rw-r--r--dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html30
-rw-r--r--dom/plugins/test/mochitest/test_positioning.html56
-rw-r--r--dom/plugins/test/mochitest/test_queryContentsScaleFactor.html31
-rw-r--r--dom/plugins/test/mochitest/test_queryContentsScaleFactorWindowed.html31
-rw-r--r--dom/plugins/test/mochitest/test_refresh_navigator_plugins.html33
42 files changed, 1945 insertions, 0 deletions
diff --git a/dom/plugins/test/mochitest/.eslintrc.js b/dom/plugins/test/mochitest/.eslintrc.js
new file mode 100644
index 0000000000..317abe7b48
--- /dev/null
+++ b/dom/plugins/test/mochitest/.eslintrc.js
@@ -0,0 +1,9 @@
+"use strict";
+
+module.exports = {
+ extends: [
+ "plugin:mozilla/browser-test",
+ "plugin:mozilla/chrome-test",
+ "plugin:mozilla/mochitest-test",
+ ],
+};
diff --git a/dom/plugins/test/mochitest/307-xo-redirect.sjs b/dom/plugins/test/mochitest/307-xo-redirect.sjs
new file mode 100644
index 0000000000..b880978cea
--- /dev/null
+++ b/dom/plugins/test/mochitest/307-xo-redirect.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response)
+{
+ response.setStatusLine(request.httpVersion, 307, "Moved temporarily");
+ response.setHeader("Location", "http://example.org/tests/dom/plugins/test/mochitest/loremipsum.txt");
+ response.setHeader("Content-Type", "text/html");
+}
diff --git a/dom/plugins/test/mochitest/block_all_plugins.html b/dom/plugins/test/mochitest/block_all_plugins.html
new file mode 100644
index 0000000000..3ccdda1373
--- /dev/null
+++ b/dom/plugins/test/mochitest/block_all_plugins.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+ <object id="object" type="application/x-shockwave-flash"></object>
+ <embed id="embed" type="application/x-shockwave-flash"></embed>
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/browser.ini b/dom/plugins/test/mochitest/browser.ini
new file mode 100644
index 0000000000..32aaf9b576
--- /dev/null
+++ b/dom/plugins/test/mochitest/browser.ini
@@ -0,0 +1,17 @@
+[DEFAULT]
+prefs =
+ plugin.load_flash_only=false
+support-files =
+ block_all_plugins.html
+ head.js
+ plugin_test.html
+ plugin_subframe_test.html
+ plugin_no_scroll_div.html
+
+[browser_blockallplugins.js]
+[browser_bug1163570.js]
+skip-if = true # Bug 1249878
+[browser_tabswitchbetweenplugins.js]
+skip-if = true #Bug 1538425
+[browser_pluginscroll.js]
+skip-if = (true || !e10s || os != "win") # Bug 1213631
diff --git a/dom/plugins/test/mochitest/browser_blockallplugins.js b/dom/plugins/test/mochitest/browser_blockallplugins.js
new file mode 100644
index 0000000000..e847f2cd23
--- /dev/null
+++ b/dom/plugins/test/mochitest/browser_blockallplugins.js
@@ -0,0 +1,66 @@
+var gTestRoot = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "http://127.0.0.1:8888/"
+);
+
+add_task(async function() {
+ registerCleanupFunction(function() {
+ gBrowser.removeCurrentTab();
+ window.focus();
+ });
+});
+
+// simple tab load helper, pilfered from browser plugin tests
+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;
+}
+
+add_task(async function() {
+ let pluginTab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser));
+ await promiseTabLoadEvent(pluginTab, gTestRoot + "block_all_plugins.html");
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
+ let doc = content.document;
+
+ let objectElt = doc.getElementById("object");
+ Assert.ok(!!objectElt, "object should exist");
+ Assert.ok(
+ objectElt instanceof Ci.nsIObjectLoadingContent,
+ "object should be an nsIObjectLoadingContent"
+ );
+ Assert.ok(
+ objectElt.pluginFallbackType ==
+ Ci.nsIObjectLoadingContent.PLUGIN_BLOCK_ALL,
+ "object should be blocked"
+ );
+
+ let embedElt = doc.getElementById("embed");
+ Assert.ok(!!embedElt, "embed should exist");
+ Assert.ok(
+ embedElt instanceof Ci.nsIObjectLoadingContent,
+ "embed should be an nsIObjectLoadingContent"
+ );
+ Assert.ok(
+ embedElt.pluginFallbackType ==
+ Ci.nsIObjectLoadingContent.PLUGIN_BLOCK_ALL,
+ "embed should be blocked"
+ );
+ });
+});
diff --git a/dom/plugins/test/mochitest/browser_bug1163570.js b/dom/plugins/test/mochitest/browser_bug1163570.js
new file mode 100644
index 0000000000..6a77728c77
--- /dev/null
+++ b/dom/plugins/test/mochitest/browser_bug1163570.js
@@ -0,0 +1,118 @@
+var gTestRoot = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "http://127.0.0.1:8888/"
+);
+
+// simple tab load helper, pilfered from browser plugin tests
+function promiseTabLoad(tab, url, eventType = "load") {
+ return new Promise(resolve => {
+ function handle(event) {
+ if (
+ event.originalTarget != tab.linkedBrowser.contentDocument ||
+ event.target.location.href == "about:blank" ||
+ (url && event.target.location.href != url)
+ ) {
+ return;
+ }
+ tab.linkedBrowser.removeEventListener(eventType, handle, true);
+ resolve(event);
+ }
+
+ tab.linkedBrowser.addEventListener(eventType, handle, true, true);
+ if (url) {
+ tab.linkedBrowser.loadURI(url);
+ }
+ });
+}
+
+// dom event listener helper
+function promiseWaitForEvent(
+ object,
+ eventName,
+ capturing = false,
+ chrome = false
+) {
+ return new Promise(resolve => {
+ function listener(event) {
+ object.removeEventListener(eventName, listener, capturing, chrome);
+ resolve(event);
+ }
+ object.addEventListener(eventName, listener, capturing, chrome);
+ });
+}
+
+add_task(async function() {
+ registerCleanupFunction(function() {
+ window.focus();
+ });
+});
+
+add_task(async function() {
+ setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
+
+ let pluginTab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser));
+ let prefTab = BrowserTestUtils.addTab(gBrowser);
+
+ await promiseTabLoad(pluginTab, gTestRoot + "plugin_test.html");
+ await promiseTabLoad(prefTab, "about:preferences");
+
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ Assert.ok(!!plugin, "plugin is loaded");
+ });
+
+ let ppromise = promiseWaitForEvent(window, "MozAfterPaint");
+ gBrowser.selectedTab = prefTab;
+ await ppromise;
+
+ // We're going to switch tabs using actual mouse clicks, which helps
+ // reproduce this bug.
+ let tabStripContainer = document.getElementById("tabbrowser-tabs");
+
+ // diagnosis if front end layout changes
+ info("-> " + tabStripContainer.tagName); // tabs
+ info("-> " + tabStripContainer.firstChild.tagName); // tab
+ info("-> " + tabStripContainer.childNodes[0].label); // test harness tab
+ info("-> " + tabStripContainer.childNodes[1].label); // plugin tab
+ info("-> " + tabStripContainer.childNodes[2].label); // preferences tab
+
+ for (let iteration = 0; iteration < 5; iteration++) {
+ ppromise = promiseWaitForEvent(window, "MozAfterPaint");
+ EventUtils.synthesizeMouseAtCenter(
+ tabStripContainer.childNodes[1],
+ {},
+ window
+ );
+ await ppromise;
+
+ await SpecialPowers.spawn(pluginTab.linkedBrowser, [], async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ Assert.ok(
+ XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible(),
+ "plugin is visible"
+ );
+ });
+
+ ppromise = promiseWaitForEvent(window, "MozAfterPaint");
+ EventUtils.synthesizeMouseAtCenter(
+ tabStripContainer.childNodes[2],
+ {},
+ window
+ );
+ await ppromise;
+
+ await SpecialPowers.spawn(pluginTab.linkedBrowser, [], async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ Assert.ok(
+ !XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible(),
+ "plugin is hidden"
+ );
+ });
+ }
+
+ gBrowser.removeTab(prefTab);
+ gBrowser.removeTab(pluginTab);
+});
diff --git a/dom/plugins/test/mochitest/browser_pluginscroll.js b/dom/plugins/test/mochitest/browser_pluginscroll.js
new file mode 100644
index 0000000000..a55651b1cc
--- /dev/null
+++ b/dom/plugins/test/mochitest/browser_pluginscroll.js
@@ -0,0 +1,417 @@
+var gTestRoot = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "http://127.0.0.1:8888/"
+);
+
+const { Preferences } = ChromeUtils.import(
+ "resource://gre/modules/Preferences.jsm"
+);
+
+/**
+ * tests for plugin windows and scroll
+ */
+
+function coordinatesRelativeToWindow(aX, aY, aElement) {
+ var targetWindow = aElement.ownerGlobal;
+ var scale = targetWindow.devicePixelRatio;
+ var rect = aElement.getBoundingClientRect();
+ return {
+ x: targetWindow.mozInnerScreenX + (rect.left + aX) * scale,
+ y: targetWindow.mozInnerScreenY + (rect.top + aY) * scale,
+ };
+}
+
+var apzEnabled =
+ Services.appinfo.fissionAutostart ||
+ Preferences.get("layers.async-pan-zoom.enabled", false);
+var pluginHideEnabled = Preferences.get(
+ "gfx.e10s.hide-plugins-for-scroll",
+ true
+);
+
+add_task(async function() {
+ registerCleanupFunction(function() {
+ setTestPluginEnabledState(
+ Ci.nsIPluginTag.STATE_CLICKTOPLAY,
+ "Test Plug-in"
+ );
+ });
+});
+
+add_task(async function() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["general.smoothScroll", true],
+ ["general.smoothScroll.other", true],
+ ["general.smoothScroll.mouseWheel", true],
+ ["general.smoothScroll.other.durationMaxMS", 2000],
+ ["general.smoothScroll.other.durationMinMS", 1999],
+ ["general.smoothScroll.mouseWheel.durationMaxMS", 2000],
+ ["general.smoothScroll.mouseWheel.durationMinMS", 1999],
+ ],
+ });
+});
+
+/*
+ * test plugin visibility when scrolling with scroll wheel and apz in a top level document.
+ */
+
+add_task(async function() {
+ let result;
+
+ if (!apzEnabled) {
+ ok(true, "nothing to test, need apz");
+ return;
+ }
+
+ if (!pluginHideEnabled) {
+ ok(true, "nothing to test, need gfx.e10s.hide-plugins-for-scroll");
+ return;
+ }
+
+ setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
+
+ let pluginTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ gTestRoot + "plugin_test.html"
+ );
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return !!plugin;
+ }
+ );
+ is(result, true, "plugin is loaded");
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, true, "plugin is visible");
+
+ let nativeId = nativeVerticalWheelEventMsg();
+ let utils = SpecialPowers.getDOMWindowUtils(window);
+ let screenCoords = coordinatesRelativeToWindow(
+ 10,
+ 10,
+ gBrowser.selectedBrowser
+ );
+ utils.sendNativeMouseScrollEvent(
+ screenCoords.x,
+ screenCoords.y,
+ nativeId,
+ 0,
+ -50,
+ 0,
+ 0,
+ 0,
+ gBrowser.selectedBrowser
+ );
+
+ await waitScrollStart(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, false, "plugin is hidden");
+
+ await waitScrollFinish(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, true, "plugin is visible");
+
+ gBrowser.removeTab(pluginTab);
+});
+
+/*
+ * test plugin visibility when scrolling with scroll wheel and apz in a sub document.
+ */
+
+add_task(async function() {
+ let result;
+
+ if (!apzEnabled) {
+ ok(true, "nothing to test, need apz");
+ return;
+ }
+
+ if (!pluginHideEnabled) {
+ ok(true, "nothing to test, need gfx.e10s.hide-plugins-for-scroll");
+ return;
+ }
+
+ setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
+
+ let pluginTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ gTestRoot + "plugin_subframe_test.html"
+ );
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return !!plugin;
+ }
+ );
+ is(result, true, "plugin is loaded");
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, true, "plugin is visible");
+
+ let nativeId = nativeVerticalWheelEventMsg();
+ let utils = SpecialPowers.getDOMWindowUtils(window);
+ let screenCoords = coordinatesRelativeToWindow(
+ 10,
+ 10,
+ gBrowser.selectedBrowser
+ );
+ utils.sendNativeMouseScrollEvent(
+ screenCoords.x,
+ screenCoords.y,
+ nativeId,
+ 0,
+ -50,
+ 0,
+ 0,
+ 0,
+ gBrowser.selectedBrowser
+ );
+
+ await waitScrollStart(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, false, "plugin is hidden");
+
+ await waitScrollFinish(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, true, "plugin is visible");
+
+ gBrowser.removeTab(pluginTab);
+});
+
+/*
+ * test visibility when scrolling with keyboard shortcuts for a top level document.
+ * This circumvents apz and relies on dom scroll, which is what we want to target
+ * for this test.
+ */
+
+add_task(async function() {
+ let result;
+
+ if (!pluginHideEnabled) {
+ ok(true, "nothing to test, need gfx.e10s.hide-plugins-for-scroll");
+ return;
+ }
+
+ setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
+
+ let pluginTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ gTestRoot + "plugin_test.html"
+ );
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return !!plugin;
+ }
+ );
+ is(result, true, "plugin is loaded");
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, true, "plugin is visible");
+
+ EventUtils.synthesizeKey("KEY_End");
+
+ await waitScrollStart(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, false, "plugin is hidden");
+
+ await waitScrollFinish(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, false, "plugin is hidden");
+
+ EventUtils.synthesizeKey("KEY_Home");
+
+ await waitScrollFinish(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, true, "plugin is visible");
+
+ gBrowser.removeTab(pluginTab);
+});
+
+/*
+ * test visibility when scrolling with keyboard shortcuts for a sub document.
+ */
+
+add_task(async function() {
+ let result;
+
+ if (!pluginHideEnabled) {
+ ok(true, "nothing to test, need gfx.e10s.hide-plugins-for-scroll");
+ return;
+ }
+
+ setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
+
+ let pluginTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ gTestRoot + "plugin_subframe_test.html"
+ );
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return !!plugin;
+ }
+ );
+ is(result, true, "plugin is loaded");
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, true, "plugin is visible");
+
+ EventUtils.synthesizeKey("KEY_End");
+
+ await waitScrollStart(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, false, "plugin is hidden");
+
+ await waitScrollFinish(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, false, "plugin is hidden");
+
+ EventUtils.synthesizeKey("KEY_Home");
+
+ await waitScrollFinish(gBrowser.selectedBrowser);
+
+ result = await SpecialPowers.spawn(
+ pluginTab.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document.getElementById("subframe").contentDocument;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ }
+ );
+ is(result, true, "plugin is visible");
+
+ gBrowser.removeTab(pluginTab);
+});
diff --git a/dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js b/dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js
new file mode 100644
index 0000000000..c6b7e10796
--- /dev/null
+++ b/dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js
@@ -0,0 +1,141 @@
+var gTestRoot = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ "http://127.0.0.1:8888/"
+);
+
+function waitForPluginVisibility(browser, shouldBeVisible, errorMessage) {
+ return new Promise((resolve, reject) => {
+ let windowUtils = window.windowUtils;
+ let lastTransactionId = windowUtils.lastTransactionId;
+ let listener = async event => {
+ let visibility = await SpecialPowers.spawn(browser, [], async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+ });
+
+ if (visibility == shouldBeVisible) {
+ window.removeEventListener("MozAfterPaint", listener);
+ resolve();
+ } else if (event && event.transactionId > lastTransactionId) {
+ // We want to allow for one failed check since we call listener
+ // directly, but if we get a MozAfterPaint notification and we
+ // still don't have the correct visibility, that's likely a
+ // problem.
+ reject(new Error("MozAfterPaint had a mismatched plugin visibility"));
+ }
+ };
+ window.addEventListener("MozAfterPaint", listener);
+ listener(null);
+ });
+}
+
+// tests that we get plugin updates when we flip between tabs that
+// have the same plugin in the same position in the page.
+
+add_task(async function() {
+ let result, tabSwitchedPromise;
+
+ setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
+
+ let testTab = gBrowser.selectedTab;
+ let pluginTab1 = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ gTestRoot + "plugin_test.html"
+ );
+ let pluginTab2 = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ gTestRoot + "plugin_test.html"
+ );
+
+ result = await SpecialPowers.spawn(
+ pluginTab1.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return !!plugin;
+ }
+ );
+ is(result, true, "plugin1 is loaded");
+
+ result = await SpecialPowers.spawn(
+ pluginTab2.linkedBrowser,
+ [],
+ async function() {
+ let doc = content.document;
+ let plugin = doc.getElementById("testplugin");
+ return !!plugin;
+ }
+ );
+ is(result, true, "plugin2 is loaded");
+
+ // plugin tab 2 should be selected
+ is(gBrowser.selectedTab == pluginTab2, true, "plugin2 is selected");
+
+ await waitForPluginVisibility(
+ pluginTab1.linkedBrowser,
+ false,
+ "plugin1 should be hidden"
+ );
+
+ await waitForPluginVisibility(
+ pluginTab2.linkedBrowser,
+ true,
+ "plugin2 should be visible"
+ );
+
+ // select plugin1 tab
+ tabSwitchedPromise = waitTabSwitched();
+ gBrowser.selectedTab = pluginTab1;
+ await tabSwitchedPromise;
+
+ await waitForPluginVisibility(
+ pluginTab1.linkedBrowser,
+ true,
+ "plugin1 should be visible"
+ );
+
+ await waitForPluginVisibility(
+ pluginTab2.linkedBrowser,
+ false,
+ "plugin2 should be hidden"
+ );
+
+ // select plugin2 tab
+ tabSwitchedPromise = waitTabSwitched();
+ gBrowser.selectedTab = pluginTab2;
+ await tabSwitchedPromise;
+
+ await waitForPluginVisibility(
+ pluginTab1.linkedBrowser,
+ false,
+ "plugin1 should be hidden"
+ );
+
+ await waitForPluginVisibility(
+ pluginTab2.linkedBrowser,
+ true,
+ "plugin2 should be visible"
+ );
+
+ // select test tab
+ tabSwitchedPromise = waitTabSwitched();
+ gBrowser.selectedTab = testTab;
+ await tabSwitchedPromise;
+
+ await waitForPluginVisibility(
+ pluginTab1.linkedBrowser,
+ false,
+ "plugin1 should be hidden"
+ );
+
+ await waitForPluginVisibility(
+ pluginTab2.linkedBrowser,
+ false,
+ "plugin2 should be hidden"
+ );
+
+ gBrowser.removeTab(pluginTab1);
+ gBrowser.removeTab(pluginTab2);
+});
diff --git a/dom/plugins/test/mochitest/file_authident.js b/dom/plugins/test/mochitest/file_authident.js
new file mode 100644
index 0000000000..d067cff223
--- /dev/null
+++ b/dom/plugins/test/mochitest/file_authident.js
@@ -0,0 +1,14 @@
+var am = Cc["@mozilla.org/network/http-auth-manager;1"].getService(
+ Ci.nsIHttpAuthManager
+);
+am.setAuthIdentity(
+ "http",
+ "mochi.test",
+ 8888,
+ "basic",
+ "testrealm",
+ "",
+ "mochi.test",
+ "user1",
+ "password1"
+);
diff --git a/dom/plugins/test/mochitest/file_bug771202.html b/dom/plugins/test/mochitest/file_bug771202.html
new file mode 100644
index 0000000000..935be65b25
--- /dev/null
+++ b/dom/plugins/test/mochitest/file_bug771202.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+ <embed id="pluginElement" type="application/x-test" width="200" height="200"></embed>
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/file_bug863792.html b/dom/plugins/test/mochitest/file_bug863792.html
new file mode 100644
index 0000000000..4a6889a563
--- /dev/null
+++ b/dom/plugins/test/mochitest/file_bug863792.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+<head>
+ <title>File for Bug 863792</title>
+
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <base href="chrome://browser/content/">
+</head>
+<body>
+<script type="application/javascript">
+
+// A plugin that removes itself from the document and inactivates said document
+// inside NPP_New. We should not leak the instance. See also test_bug854082
+
+var outerwindow = window;
+var i = document.createElement("iframe");
+i.width = 500;
+i.height = 500;
+var ob = document.body;
+document.body.appendChild(i);
+i.addEventListener("load", function loaded() {
+ var id = i.contentDocument;
+ var e = id.createElement("embed");
+ e.width = 200;
+ e.height = 200;
+ e.type = "application/x-test";
+ e.__defineSetter__("pluginFoundElement", function() {
+ window.console.log("pluginFoundElement");
+ e.style.display = "none";
+ e.clientTop;
+ i.removeEventListener("load", loaded);
+ ob.removeChild(i);
+ id.body.clientTop;
+ id.body.removeChild(e);
+ });
+ id.body.appendChild(e);
+ e.clientTop;
+ e = id = i = ob = null;
+ SpecialPowers.forceCC(); SpecialPowers.forceGC();
+});
+</script>
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/head.js b/dom/plugins/test/mochitest/head.js
new file mode 100644
index 0000000000..b9242f2932
--- /dev/null
+++ b/dom/plugins/test/mochitest/head.js
@@ -0,0 +1,147 @@
+/**
+ * Waits for a tab switch.
+ */
+function waitTabSwitched() {
+ return new Promise(resolve => {
+ gBrowser.addEventListener(
+ "TabSwitchDone",
+ function() {
+ executeSoon(resolve);
+ },
+ { once: true }
+ );
+ });
+}
+
+/**
+ * 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);
+ }
+ });
+}
+
+/**
+ * Platform string helper for nativeVerticalWheelEventMsg
+ */
+function getPlatform() {
+ if (navigator.platform.indexOf("Win") == 0) {
+ return "windows";
+ }
+ if (navigator.platform.indexOf("Mac") == 0) {
+ return "mac";
+ }
+ if (navigator.platform.indexOf("Linux") == 0) {
+ return "linux";
+ }
+ return "unknown";
+}
+
+/**
+ * Returns a native wheel scroll event id for dom window
+ * uitls sendNativeMouseScrollEvent.
+ */
+function nativeVerticalWheelEventMsg() {
+ switch (getPlatform()) {
+ case "windows":
+ return 0x020a; // WM_MOUSEWHEEL
+ case "mac":
+ return 0; // value is unused, can be anything
+ case "linux":
+ return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
+ }
+ throw new Error(
+ "Native wheel events not supported on platform " + getPlatform()
+ );
+}
+
+/**
+ * Waits for the first dom "scroll" event.
+ */
+function waitScrollStart(aTarget) {
+ return new Promise((resolve, reject) => {
+ aTarget.addEventListener(
+ "scroll",
+ function(event) {
+ resolve(event);
+ },
+ { capture: true, once: true }
+ );
+ });
+}
+
+/**
+ * Waits for the last dom "scroll" event which generally indicates
+ * a scroll operation is complete. To detect this the helper waits
+ * 1 second intervals checking for scroll events from aTarget. If
+ * a scroll event is not received during that time, it considers
+ * the scroll operation complete. Not super accurate, be careful.
+ */
+function waitScrollFinish(aTarget) {
+ return new Promise((resolve, reject) => {
+ let recent = false;
+ let count = 0;
+ function listener(event) {
+ recent = true;
+ }
+ aTarget.addEventListener("scroll", listener, true);
+ setInterval(function() {
+ // one second passed and we didn't receive a scroll event.
+ if (!recent) {
+ aTarget.removeEventListener("scroll", listener, true);
+ resolve();
+ return;
+ }
+ recent = false;
+ // ten seconds
+ if (count > 10) {
+ aTarget.removeEventListener("scroll", listener, true);
+ reject();
+ }
+ }, 1000);
+ });
+}
+
+/**
+ * Set a plugin activation state. See nsIPluginTag for
+ * supported states. Affected plugin default to the first
+ * test plugin.
+ */
+function setTestPluginEnabledState(aState, aPluginName) {
+ let name = aPluginName || "Test Plug-in";
+ let resolved = false;
+ SpecialPowers.setTestPluginEnabledState(aState, name).then(() => {
+ resolved = true;
+ });
+ SpecialPowers.Services.tm.spinEventLoopUntil(() => resolved);
+}
+
+/**
+ * Returns the chrome side nsIPluginTag for this plugin, helper for
+ * setTestPluginEnabledState.
+ */
+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;
+}
diff --git a/dom/plugins/test/mochitest/large-pic.jpg b/dom/plugins/test/mochitest/large-pic.jpg
new file mode 100644
index 0000000000..b167f6b9ba
--- /dev/null
+++ b/dom/plugins/test/mochitest/large-pic.jpg
Binary files differ
diff --git a/dom/plugins/test/mochitest/loremipsum.txt b/dom/plugins/test/mochitest/loremipsum.txt
new file mode 100644
index 0000000000..c5becca596
--- /dev/null
+++ b/dom/plugins/test/mochitest/loremipsum.txt
@@ -0,0 +1,11 @@
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut laboreet dolore magna aliquyam erat.
+
+Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. \ No newline at end of file
diff --git a/dom/plugins/test/mochitest/loremipsum.xtest b/dom/plugins/test/mochitest/loremipsum.xtest
new file mode 100644
index 0000000000..c5becca596
--- /dev/null
+++ b/dom/plugins/test/mochitest/loremipsum.xtest
@@ -0,0 +1,11 @@
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut laboreet dolore magna aliquyam erat.
+
+Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. \ No newline at end of file
diff --git a/dom/plugins/test/mochitest/loremipsum.xtest^headers^ b/dom/plugins/test/mochitest/loremipsum.xtest^headers^
new file mode 100644
index 0000000000..8dd7784af4
--- /dev/null
+++ b/dom/plugins/test/mochitest/loremipsum.xtest^headers^
@@ -0,0 +1 @@
+Content-Type: application/x-test
diff --git a/dom/plugins/test/mochitest/loremipsum_file.txt b/dom/plugins/test/mochitest/loremipsum_file.txt
new file mode 100644
index 0000000000..c5becca596
--- /dev/null
+++ b/dom/plugins/test/mochitest/loremipsum_file.txt
@@ -0,0 +1,11 @@
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut laboreet dolore magna aliquyam erat.
+
+Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. \ No newline at end of file
diff --git a/dom/plugins/test/mochitest/loremipsum_nocache.txt b/dom/plugins/test/mochitest/loremipsum_nocache.txt
new file mode 100644
index 0000000000..c5becca596
--- /dev/null
+++ b/dom/plugins/test/mochitest/loremipsum_nocache.txt
@@ -0,0 +1,11 @@
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut laboreet dolore magna aliquyam erat.
+
+Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. \ No newline at end of file
diff --git a/dom/plugins/test/mochitest/loremipsum_nocache.txt^headers^ b/dom/plugins/test/mochitest/loremipsum_nocache.txt^headers^
new file mode 100644
index 0000000000..12a01c4a22
--- /dev/null
+++ b/dom/plugins/test/mochitest/loremipsum_nocache.txt^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/plugins/test/mochitest/mixed_case_mime.sjs b/dom/plugins/test/mochitest/mixed_case_mime.sjs
new file mode 100644
index 0000000000..1901bb74d8
--- /dev/null
+++ b/dom/plugins/test/mochitest/mixed_case_mime.sjs
@@ -0,0 +1,8 @@
+function handleRequest(request, response)
+{
+ response.processAsync();
+ response.setHeader("Content-Type", "image/pNG", false);
+
+ response.write("Hello world.\n");
+ response.finish();
+}
diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochitest/mochitest.ini
new file mode 100644
index 0000000000..79ed62167a
--- /dev/null
+++ b/dom/plugins/test/mochitest/mochitest.ini
@@ -0,0 +1,45 @@
+[DEFAULT]
+prefs =
+ plugin.load_flash_only=false
+skip-if = headless # crash on shutdown, no other failures
+support-files =
+ 307-xo-redirect.sjs
+ file_authident.js
+ file_bug771202.html
+ file_bug863792.html
+ large-pic.jpg
+ loremipsum.txt
+ loremipsum.xtest
+ loremipsum.xtest^headers^
+ loremipsum_file.txt
+ loremipsum_nocache.txt
+ loremipsum_nocache.txt^headers^
+ mixed_case_mime.sjs
+ neverending.sjs
+ npruntime_identifiers_subpage.html
+ plugin-stream-referer.sjs
+ plugin_window.html
+ pluginstream.js
+ post.sjs
+ plugin-utils.js
+
+[test_hanging.html]
+skip-if = !crashreporter || e10s
+[test_mixed_case_mime.html]
+skip-if = (processor == 'aarch64' && os == 'win')
+reason = Plugins are not supported on Windows/AArch64
+[test_plugin_fallback_focus.html]
+[test_plugin_scroll_painting.html]
+skip-if = true # Bug 596491
+[test_pluginstream_geturl.html]
+skip-if = true # Bug 1267432
+[test_pluginstream_geturlnotify.html]
+skip-if = true # Bug 1267432
+[test_positioning.html]
+skip-if = true # disabled due to oddness, perhaps scrolling of the mochitest window?
+[test_queryContentsScaleFactor.html]
+skip-if = (toolkit != "cocoa") || (os != "win")
+[test_queryContentsScaleFactorWindowed.html]
+skip-if = (toolkit != "cocoa") || (os != "win")
+[test_refresh_navigator_plugins.html]
+skip-if = e10s # Bug 1090576
diff --git a/dom/plugins/test/mochitest/neverending.sjs b/dom/plugins/test/mochitest/neverending.sjs
new file mode 100644
index 0000000000..1576ce344c
--- /dev/null
+++ b/dom/plugins/test/mochitest/neverending.sjs
@@ -0,0 +1,16 @@
+var timer = null; // declare timer outside to prevent premature GC
+function handleRequest(request, response)
+{
+ response.processAsync();
+ response.setHeader("Content-Type", "text/plain", false);
+
+ for (var i = 0; i < 1000; ++i)
+ response.write("Hello... ");
+
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.write("world.\n");
+ response.finish();
+ }, 10 * 1000 /* 10 secs */, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
diff --git a/dom/plugins/test/mochitest/npruntime_identifiers_subpage.html b/dom/plugins/test/mochitest/npruntime_identifiers_subpage.html
new file mode 100644
index 0000000000..38c62e017b
--- /dev/null
+++ b/dom/plugins/test/mochitest/npruntime_identifiers_subpage.html
@@ -0,0 +1,4 @@
+<html>
+ <body>
+ <embed id="plugin1" type="application/x-test" width="400" height="100">
+ </embed>
diff --git a/dom/plugins/test/mochitest/plugin-stream-referer.sjs b/dom/plugins/test/mochitest/plugin-stream-referer.sjs
new file mode 100644
index 0000000000..a1c9692c95
--- /dev/null
+++ b/dom/plugins/test/mochitest/plugin-stream-referer.sjs
@@ -0,0 +1,12 @@
+function handleRequest(request, response)
+{
+ response.setHeader('Content-Type', 'text/plain', false);
+ response.setHeader('Cache-Control', 'no-cache', false);
+ response.setHeader('Content-Type', 'application/x-test', false);
+ if (request.hasHeader('Referer')) {
+ response.write('Referer found: ' + request.getHeader('Referer'));
+ }
+ else {
+ response.write('No Referer found');
+ }
+}
diff --git a/dom/plugins/test/mochitest/plugin-utils.js b/dom/plugins/test/mochitest/plugin-utils.js
new file mode 100644
index 0000000000..1d35d2b049
--- /dev/null
+++ b/dom/plugins/test/mochitest/plugin-utils.js
@@ -0,0 +1,147 @@
+function paintCountIs(plugin, expected, msg) {
+ var count = plugin.getPaintCount();
+ var realExpected = expected;
+ ++realExpected; // extra paint at startup for all async-rendering plugins
+ ok(
+ realExpected == count,
+ msg +
+ " (expected " +
+ expected +
+ " independent paints, expected " +
+ realExpected +
+ " logged paints, got " +
+ count +
+ " actual paints)"
+ );
+}
+
+function getTestPlugin(pluginName) {
+ var ph = SpecialPowers.Cc["@mozilla.org/plugin/host;1"].getService(
+ SpecialPowers.Ci.nsIPluginHost
+ );
+ var tags = ph.getPluginTags();
+ var name = pluginName || "Test Plug-in";
+ for (var tag of tags) {
+ if (tag.name == name) {
+ return tag;
+ }
+ }
+
+ ok(false, "Could not find plugin tag with plugin name '" + name + "'");
+ return null;
+}
+
+// call this to set the test plugin(s) initially expected enabled state.
+// it will automatically be reset to it's previous value after the test
+// ends
+function setTestPluginEnabledState(newEnabledState, pluginName) {
+ var oldEnabledState = SpecialPowers.setTestPluginEnabledState(
+ newEnabledState,
+ pluginName
+ );
+ var plugin = getTestPlugin(pluginName);
+ // Run a nested event loop to wait for the preference change to
+ // propagate to the child. Yuck!
+ SpecialPowers.Services.tm.spinEventLoopUntil(() => {
+ return plugin.enabledState == newEnabledState;
+ });
+ SimpleTest.registerCleanupFunction(async function() {
+ return SpecialPowers.setTestPluginEnabledState(
+ await oldEnabledState,
+ pluginName
+ );
+ });
+}
+
+function crashAndGetCrashServiceRecord(crashMethodName, callback) {
+ var crashMan = SpecialPowers.Cu.import("resource://gre/modules/Services.jsm")
+ .Services.crashmanager;
+
+ // First, clear the crash record store.
+ info("Waiting for pruneOldCrashes");
+ var future = new Date(Date.now() + 1000 * 60 * 60 * 24);
+ crashMan.pruneOldCrashes(future).then(
+ function() {
+ var iframe = document.getElementById("iframe1");
+ var p = iframe.contentDocument.getElementById("plugin1");
+
+ var crashDateMS = Date.now();
+ try {
+ p[crashMethodName]();
+ ok(false, "p." + crashMethodName + "() should throw an exception");
+ } catch (e) {
+ ok(true, "p." + crashMethodName + "() should throw an exception");
+ }
+
+ // The crash record store is written and read back asyncly, so poll for
+ // the new record.
+ function tryGetCrash() {
+ info("Waiting for getCrashes");
+ crashMan.getCrashes().then(
+ SpecialPowers.wrapCallback(function(crashes) {
+ if (crashes.length) {
+ is(crashes.length, 1, "There should be only one record");
+ var crash = SpecialPowers.wrap(crashes[0]);
+ ok(!!crash.id, "Record should have an ID");
+ ok(!!crash.crashDate, "Record should have a crash date");
+ var dateMS = crash.crashDate.valueOf();
+ var twoMin = 1000 * 60 * 2;
+ ok(
+ crashDateMS - twoMin <= dateMS &&
+ dateMS <= crashDateMS + twoMin,
+ "Record's crash date should be nowish: " +
+ "now=" +
+ crashDateMS +
+ " recordDate=" +
+ dateMS
+ );
+ callback(crashMan, crash);
+ } else {
+ setTimeout(tryGetCrash, 1000);
+ }
+ }),
+ function(err) {
+ ok(false, "Error getting crashes: " + err);
+ SimpleTest.finish();
+ }
+ );
+ }
+ setTimeout(tryGetCrash, 1000);
+ },
+ function() {
+ ok(false, "pruneOldCrashes error");
+ SimpleTest.finish();
+ }
+ );
+}
+
+/**
+ * Returns a promise which resolves on `mozFullScreenChange`.
+ */
+function promiseFullScreenChange() {
+ return new Promise(resolve => {
+ document.addEventListener(
+ "fullscreenchange",
+ function(e) {
+ resolve();
+ },
+ { once: true }
+ );
+ });
+}
+
+/**
+ * Crashes target plugin. Returns a promise; resolves on successful crash,
+ * rejects otherwise.
+ * @param plugin Target plugin to attempt to crash.
+ */
+function crashPlugin(plugin) {
+ return new Promise((resolve, reject) => {
+ try {
+ plugin.crash();
+ reject();
+ } catch (e) {
+ resolve();
+ }
+ });
+}
diff --git a/dom/plugins/test/mochitest/plugin_no_scroll_div.html b/dom/plugins/test/mochitest/plugin_no_scroll_div.html
new file mode 100644
index 0000000000..b28f6d6ffb
--- /dev/null
+++ b/dom/plugins/test/mochitest/plugin_no_scroll_div.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+ <embed id="testplugin" type="application/x-test" drawmode="solid" color="ff00ff00" wmode="window"
+ style="position:absolute; top:5px; left:5px; width:500px; height:250px">
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/plugin_subframe_test.html b/dom/plugins/test/mochitest/plugin_subframe_test.html
new file mode 100644
index 0000000000..598521d57e
--- /dev/null
+++ b/dom/plugins/test/mochitest/plugin_subframe_test.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+ <iframe id="subframe" style="width:510px; height:260px;" src="plugin_no_scroll_div.html"></iframe>
+ <div style="display:block; height:3000px;"></div>
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/plugin_test.html b/dom/plugins/test/mochitest/plugin_test.html
new file mode 100644
index 0000000000..88b70e8ee6
--- /dev/null
+++ b/dom/plugins/test/mochitest/plugin_test.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+ <embed id="testplugin" type="application/x-test" drawmode="solid" color="ff00ff00" wmode="window"
+ style="position:absolute; top:50px; left:50px; width:500px; height:250px">
+<div style="display:block; height:3000px;"></div>
+
+<iframe id="subf" src="about:blank" width="300" height="300"></iframe>
+
+<a href="about:blank" id="aboutlink">Navigate to about:blank</a>
+
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/plugin_window.html b/dom/plugins/test/mochitest/plugin_window.html
new file mode 100644
index 0000000000..d3a298e89c
--- /dev/null
+++ b/dom/plugins/test/mochitest/plugin_window.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>NPAPI Stream Tests</title>
+</head>
+<body onload="doTest()">
+<p id="display"></p>
+<div id="content" style="display: none">
+This is a plugin test window.
+</div>
+<div id="test">
+<script class="testbody" type="text/javascript">
+
+function doTest() {
+ window.opener.continueTest();
+}
+
+</script>
+</div>
+</body>
+
+</html>
+
diff --git a/dom/plugins/test/mochitest/pluginstream.js b/dom/plugins/test/mochitest/pluginstream.js
new file mode 100644
index 0000000000..c4ab769d51
--- /dev/null
+++ b/dom/plugins/test/mochitest/pluginstream.js
@@ -0,0 +1,46 @@
+SimpleTest.waitForExplicitFinish();
+
+function frameLoaded(finishWhenCalled = true, lastObject = false) {
+ var testframe = document.getElementById("testframe");
+ function getNode(list) {
+ if (list.length === 0) {
+ return undefined;
+ }
+ return lastObject ? list[list.length - 1] : list[0];
+ }
+ var embed = getNode(document.getElementsByTagName("embed"));
+ if (undefined === embed) {
+ embed = getNode(document.getElementsByTagName("object"));
+ }
+
+ // In the file:// URI case, this ends up being cross-origin.
+ // Skip these checks in that case.
+ if (testframe.contentDocument) {
+ var content = testframe.contentDocument.body.innerHTML;
+ if (!content.length) {
+ return;
+ }
+
+ var filename =
+ embed.getAttribute("src") ||
+ embed.getAttribute("geturl") ||
+ embed.getAttribute("geturlnotify") ||
+ embed.getAttribute("data");
+
+ var req = new XMLHttpRequest();
+ req.open("GET", filename, false);
+ req.overrideMimeType("text/plain; charset=x-user-defined");
+ req.send(null);
+ is(req.status, 200, "bad XMLHttpRequest status");
+ is(
+ content,
+ req.responseText.replace(/\r\n/g, "\n"),
+ "content doesn't match"
+ );
+ }
+
+ is(embed.getError(), "pass", "plugin reported error");
+ if (finishWhenCalled) {
+ SimpleTest.finish();
+ }
+}
diff --git a/dom/plugins/test/mochitest/post.sjs b/dom/plugins/test/mochitest/post.sjs
new file mode 100644
index 0000000000..b391dbdd81
--- /dev/null
+++ b/dom/plugins/test/mochitest/post.sjs
@@ -0,0 +1,17 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function handleRequest(request, response)
+{
+ var body = "";
+ var bodyStream = new BinaryInputStream(request.bodyInputStream);
+ var bytes = [], avail = 0;
+ while ((avail = bodyStream.available()) > 0)
+ body += String.fromCharCode.apply(String, bodyStream.readByteArray(avail));
+
+ response.setHeader("Content-Type", "text/html", false);
+ response.write(body);
+}
+
diff --git a/dom/plugins/test/mochitest/test_hanging.html b/dom/plugins/test/mochitest/test_hanging.html
new file mode 100644
index 0000000000..b6dd1b12a7
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_hanging.html
@@ -0,0 +1,59 @@
+<head>
+ <title>Plugin hanging</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+
+<body>
+ <script class="testbody" type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+
+ window.frameLoaded = function frameLoaded_toCrash() {
+ SimpleTest.expectChildProcessCrash();
+
+ // the default timeout is annoying high for mochitest runs
+ var timeoutPref = "dom.ipc.plugins.timeoutSecs";
+ SpecialPowers.setIntPref(timeoutPref, 5);
+
+ var iframe = document.getElementById("iframe1");
+ var p = iframe.contentDocument.getElementById("plugin1");
+
+ p.setColor("FFFF00FF");
+
+ try {
+ p.hang();
+ ok(false, "p.hang() should throw an exception");
+ } catch (e) {
+ ok(true, "p.hang() should throw an exception");
+ }
+
+ try {
+ p.setColor("FFFF0000");
+ ok(false, "p.setColor should throw after the plugin crashes");
+ } catch (e) {
+ ok(true, "p.setColor should throw after the plugin crashes");
+ }
+
+ window.frameLoaded = function reloaded() {
+ var p1 = iframe.contentDocument.getElementById("plugin1");
+ try {
+ p1.setColor("FF00FF00");
+ ok(true, "Reloading worked");
+ } catch (e) {
+ ok(false, "Reloading didn't give us a usable plugin");
+ }
+
+ try {
+ SpecialPowers.clearUserPref(timeoutPref);
+ } catch (e) {
+ ok(false, "Couldn't reset timeout pref");
+ }
+
+ SimpleTest.finish();
+ };
+
+ iframe.contentWindow.location.reload();
+ };
+
+ </script>
+ <iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
diff --git a/dom/plugins/test/mochitest/test_mixed_case_mime.html b/dom/plugins/test/mochitest/test_mixed_case_mime.html
new file mode 100644
index 0000000000..85e5f19ac9
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_mixed_case_mime.html
@@ -0,0 +1,25 @@
+<body>
+<head>
+ <title>Test mixed case mimetype for plugins</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script>
+ SimpleTest.expectAssertions(0, 1);
+
+ SimpleTest.waitForExplicitFinish();
+
+ function frameLoaded() {
+ var contentDocument = document.getElementById("testframe").contentDocument;
+ ok(contentDocument.body.innerHTML.length > 0, "Frame content shouldn't be empty.");
+ ok(contentDocument.images.length > 0, "Frame content should have an image.");
+ SimpleTest.finish();
+ }
+</script>
+</head>
+<body>
+ <p id="display"></p>
+
+ <iframe id="testframe" name="testframe" onload="frameLoaded()" src="mixed_case_mime.sjs"></iframe>
+
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/test_plugin_fallback_focus.html b/dom/plugins/test/mochitest/test_plugin_fallback_focus.html
new file mode 100644
index 0000000000..e89abb44df
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_plugin_fallback_focus.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test that plugins reject focus</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="content">
+ <object id="obj_elt" type="application/x-shockwave-flash"></object>
+ <object tabindex='0' id="obj_elt_with_idx" type="application/x-shockwave-flash"></object>
+ <embed id="embed_elt" type="application/x-shockwave-flash"></embed>
+</div>
+<script type="application/javascript">
+var objElt = document.getElementById('obj_elt');
+var objEltWithIdx = document.getElementById('obj_elt_with_idx');
+var embedElt = document.getElementById('embed_elt');
+
+function checkHasFocus(expected, typeOfElts, elt) {
+ ok((document.activeElement == elt) == expected,
+ typeOfElts + " element should " + (expected ? "" : "not ") + "accept focus");
+}
+
+function checkNoneHasFocus(typeOfElts) {
+ checkHasFocus(false, typeOfElts + " <object>", objElt);
+ checkHasFocus(false, typeOfElts + " <object> with tabindex", objEltWithIdx);
+ checkHasFocus(false, typeOfElts + " <embed>", embedElt);
+}
+
+function checkFocusable(expected, typeOfElts, elt) {
+ elt.focus();
+ checkHasFocus(expected, typeOfElts, elt);
+}
+
+// As plugins, object and embed elements are not given focus
+ok(objElt != null, "object element should exist");
+ok(objEltWithIdx != null, "object element with tabindex should exist");
+ok(embedElt != null, "embed element should exist");
+
+// As plugins, obj/embed_elt can not take focus
+checkNoneHasFocus("plugin");
+
+// Switch obj/embed_elt attributes from plugin to image
+objElt.data = "large-pic.jpg";
+objElt.width = 100;
+objElt.height = 100;
+objElt.type = "image/jpg";
+objEltWithIdx.data = "large-pic.jpg";
+objEltWithIdx.width = 100;
+objEltWithIdx.height = 100;
+objEltWithIdx.type = "image/jpg";
+embedElt.src = "large-pic.jpg";
+embedElt.width = 100;
+embedElt.height = 100;
+embedElt.type = "image/jpg";
+
+// As images, obj/embed_elt can take focus as image
+// object image elements require a tabindex to accept focus.
+// embed elements must be reparented before new type is recognized.
+checkFocusable(false, "<object> image", objElt);
+checkFocusable(true, "<object> image with tabindex", objEltWithIdx);
+checkFocusable(false, "<embed> plugin with image attribs before reparenting", embedElt);
+embedElt.parentNode.appendChild(embedElt);
+checkFocusable(true, "<embed> image", embedElt);
+
+// Switch obj/embed_elt attributes from image to plugin
+objElt.type = "application/x-shockwave-flash";
+embedElt.type = "application/x-shockwave-flash";
+
+// embed elements must be reparented before new type is recognized.
+checkFocusable(true, "<embed> image with plugin attribs", embedElt);
+embedElt.parentNode.appendChild(embedElt);
+checkNoneHasFocus("plugin");
+</script>
+</body>
+</html>
+
+
diff --git a/dom/plugins/test/mochitest/test_plugin_scroll_invalidation.html b/dom/plugins/test/mochitest/test_plugin_scroll_invalidation.html
new file mode 100644
index 0000000000..5fdd2a7b6c
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_plugin_scroll_invalidation.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for plugin child widgets not being invalidated by scrolling</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="initialize()">
+<script type="application/javascript">
+setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED,
+ "Test Plug-in");
+</script>
+
+<p id="display">
+ <iframe id="i" src="plugin_scroll_invalidation.html"
+ width="50" height="50" scrolling="no"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var scrolling;
+var scrolling_plugins = [];
+var paint_waiter;
+var last_paint_counts;
+
+function initialize() {
+ scrolling = document.getElementById("i").contentWindow;
+ scrolling_plugins = scrolling.document.querySelectorAll("embed.scrolling");
+ paint_waiter = scrolling.document.getElementById("paint-waiter");
+
+ scrolling.scrollTo(50, 45);
+
+ is(paint_waiter.getPaintCount(), 0, "zero-sized plugin not painted");
+
+ waitForPaint(scrollAround);
+}
+
+function scrollAround() {
+ var paints = getPaintCounts();
+
+ for (var i = 0; i < paints.length; ++i) {
+ isnot(paints[i], 0, "embed " + scrolling_plugins[i].id + " is painted");
+ }
+
+ last_paint_counts = paints;
+
+ scrolling.scrollBy(-5, 5);
+ scrolling.scrollBy(5, 5);
+ scrolling.scrollBy(5, -5);
+ scrolling.scrollBy(-5, -5);
+
+ scrolling.scrollTo(45, 45);
+ scrolling.scrollBy(10, 0);
+ scrolling.scrollBy(0, 10);
+ scrolling.scrollBy(-10, 0);
+ scrolling.scrollBy(0, -10);
+
+ waitForPaint(done);
+}
+
+function done() {
+ var paints = getPaintCounts();
+ for (var i = 0; i < paints.length; ++i) {
+ is(paints[i], last_paint_counts[i], "embed " + scrolling_plugins[i].id + " is not painted on scroll");
+ }
+ SimpleTest.finish();
+}
+
+// Waits for the paint_waiter plugin to be repainted and then
+// calls 'func' to continue.
+function waitForPaint(func) {
+ paint_waiter.last_paint_count = paint_waiter.getPaintCount();
+
+ paint_waiter.style.left = scrolling.scrollX + "px";
+ paint_waiter.style.top = scrolling.scrollY + "px";
+
+ // Fiddle with the style in a way that should force some repainting
+ paint_waiter.style.width =
+ (paint_waiter.getBoundingClientRect().width + 1) + "px";
+ paint_waiter.style.height = "1px";
+
+ function waitForPaintHelper() {
+ if (paint_waiter.getPaintCount() != paint_waiter.last_paint_count) {
+ setTimeout(func, 0);
+ return;
+ }
+ setTimeout(waitForPaintHelper, 0);
+ }
+ waitForPaintHelper();
+}
+
+function getPaintCounts() {
+ var result = [];
+ for (var i = 0; i < scrolling_plugins.length; ++i) {
+ result[i] = scrolling_plugins[i].getPaintCount();
+ }
+ return result;
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/test_plugin_scroll_painting.html b/dom/plugins/test/mochitest/test_plugin_scroll_painting.html
new file mode 100644
index 0000000000..1041b948da
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_plugin_scroll_painting.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that scrolling a windowless plugin doesn't force us to repaint it</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="plugin-utils.js"></script>
+ <script type="text/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="runTest()">
+<p id="display"></p>
+ <embed id="plugin" type="application/x-test" style="width:50px; height:10px; margin-top:20px;"></embed>
+</div>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var container = document.documentElement;
+container.scrollTop = 0;
+var plugin = document.getElementById("plugin");
+var pluginTop;
+var beforeScrollPaintCount;
+
+function waitForScroll() {
+ if (plugin.getEdge(1) >= pluginTop) {
+ setTimeout(waitForScroll, 0);
+ return;
+ }
+
+ is(plugin.getPaintCount(), beforeScrollPaintCount, "plugin should not paint due to scrolling");
+ SimpleTest.finish();
+}
+
+function waitForInitialScroll() {
+ if (plugin.getEdge(1) >= pluginTop) {
+ setTimeout(waitForInitialScroll, 0);
+ return;
+ }
+
+ pluginTop = plugin.getEdge(1);
+ beforeScrollPaintCount = plugin.getPaintCount();
+ container.scrollTop = 20;
+ waitForScroll();
+}
+
+function runTest() {
+ document.body.offsetTop;
+ pluginTop = plugin.getEdge(1);
+ container.scrollTop = 10;
+ waitForInitialScroll();
+}
+</script>
+
+<div style="height:4000px;"></div>
+
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/test_pluginstream_geturl.html b/dom/plugins/test/mochitest/test_pluginstream_geturl.html
new file mode 100644
index 0000000000..fe69427a42
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_pluginstream_geturl.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+ <title>NPAPI NPN_GetURL NPStream Test</title>
+ <script type="text/javascript"
+ src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript"
+ src="pluginstream.js"></script>
+ <script type="text/javascript" src="plugin-utils.js"></script>
+ <script type="text/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <link rel="stylesheet" type="text/css"
+ href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+ <p id="display"></p>
+
+ <iframe id="testframe" name="testframe" onload="frameLoaded()"></iframe>
+
+ <!--
+ - The plugin reports that data can be sent to
+ - it in 1024-byte chunks, and the stream is initiated by a call to
+ - NPN_GetURL.
+ -->
+ <embed geturl="loremipsum.txt" streammode="normal"
+ streamchunksize="1024" frame="testframe"
+ id="embedtest" style="width: 400px; height: 100px;"
+ type="application/x-test"></embed>
+ </body>
+ </html>
+ \ No newline at end of file
diff --git a/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html b/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html
new file mode 100644
index 0000000000..ee4c2b119d
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html
@@ -0,0 +1,30 @@
+<body>
+<head>
+ <title>NPAPI NPN_GetURLNotify Test</title>
+ <script type="text/javascript"
+ src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript"
+ src="pluginstream.js"></script>
+ <script type="text/javascript" src="plugin-utils.js"></script>
+ <script type="text/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <link rel="stylesheet" type="text/css"
+ href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+ <p id="display"></p>
+
+ <iframe id="testframe" name="testframe" onload="frameLoaded()"></iframe>
+
+ <!--
+ - The stream is requested by
+ - the plugin using NPN_GetURLNotify, and the plugin does not send the
+ - stream back to the browser until NPP_URLNotify is called.
+ -->
+ <embed geturlnotify="loremipsum.txt" streammode="normal"
+ streamchunksize="1024" frame="testframe"
+ id="embedtest" style="width: 400px; height: 100px;"
+ type="application/x-test"></embed>
+ </body>
+ </html>
diff --git a/dom/plugins/test/mochitest/test_positioning.html b/dom/plugins/test/mochitest/test_positioning.html
new file mode 100644
index 0000000000..b73f4b06fd
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_positioning.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test whether windowless plugins receive correct visible/invisible notifications.</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="plugin-utils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style type="text/css">
+ body {
+ height: 10000px;
+ }
+ </style>
+
+<body onload="startTest()">
+ <p id="display"></p>
+
+ <script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+
+ var p = null;
+
+ function startTest() {
+ p = document.getElementById("theplugin");
+
+ // Wait for the plugin to have painted once
+ var interval = setInterval(function() {
+ if (!p.getPaintCount())
+ return;
+
+ clearInterval(interval);
+ doScroll();
+ }, 100);
+ }
+
+ const kScrollAmount = 1000;
+ var startY;
+
+ function doScroll() {
+ let y = p.getWindowPosition()[1];
+ startY = y;
+
+ scrollBy(0, kScrollAmount);
+ setTimeout(checkScroll, 500);
+ }
+
+ function checkScroll() {
+ let y = p.getWindowPosition()[1];
+
+ is(y, startY - kScrollAmount, "Window should be informed of its new position.");
+ SimpleTest.finish();
+ }
+ </script>
+
+ <embed id="theplugin" type="application/x-test" width="200" height="200"></embed>
diff --git a/dom/plugins/test/mochitest/test_queryContentsScaleFactor.html b/dom/plugins/test/mochitest/test_queryContentsScaleFactor.html
new file mode 100644
index 0000000000..565c1494f4
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_queryContentsScaleFactor.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+ <title>NPAPI NPNVcontentsScaleFactor Test</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+</head>
+
+<body onload="runTests()">
+ <script class="testbody" type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+
+ function runTests() {
+ var pluginElement = document.getElementById("plugin");
+ var contentsScaleFactor;
+ var exceptionThrown = false;
+ try {
+ contentsScaleFactor = pluginElement.queryContentsScaleFactor();
+ } catch (e) {
+ exceptionThrown = true;
+ }
+ is(exceptionThrown, false, "Exception thrown getting contents scale factor.");
+ is(isNaN(contentsScaleFactor), false, "Invalid return getting contents scale factor");
+ ok(true, "Got Scale Factor of " + contentsScaleFactor);
+ SimpleTest.finish();
+ }
+ </script>
+
+ <embed id="plugin" type="application/x-test" width="400" height="400"></embed>
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/test_queryContentsScaleFactorWindowed.html b/dom/plugins/test/mochitest/test_queryContentsScaleFactorWindowed.html
new file mode 100644
index 0000000000..8db018fd66
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_queryContentsScaleFactorWindowed.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+ <title>NPAPI NPNVcontentsScaleFactor Test</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="utils.js"></script>
+</head>
+
+<body onload="runTests()">
+ <script class="testbody" type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+
+ function runTests() {
+ var pluginElement = document.getElementById("plugin");
+ var contentsScaleFactor;
+ var exceptionThrown = false;
+ try {
+ contentsScaleFactor = pluginElement.queryContentsScaleFactor();
+ } catch (e) {
+ exceptionThrown = true;
+ }
+ is(exceptionThrown, false, "Exception thrown getting contents scale factor.");
+ is(isNaN(contentsScaleFactor), false, "Invalid return getting contents scale factor");
+ ok(true, "Got Scale Factor of " + contentsScaleFactor);
+ SimpleTest.finish();
+ }
+ </script>
+
+ <embed id="plugin" type="application/x-test" width="400" height="400" wmode="window"></embed>
+</body>
+</html>
diff --git a/dom/plugins/test/mochitest/test_refresh_navigator_plugins.html b/dom/plugins/test/mochitest/test_refresh_navigator_plugins.html
new file mode 100644
index 0000000000..fc54370a0b
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_refresh_navigator_plugins.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- bug 820708 -->
+<html>
+ <head>
+ <meta><charset="utf-8"/>
+ <title>Test Refreshing navigator.plugins (bug 820708)</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+ <link rel="stylesheet" type="text/css"
+ href="/tests/SimpleTest/test.css">
+ </head>
+ <body>
+ <p id="display"></p>
+ <script class="testbody" type="application/javascript">
+ "use strict";
+
+ SimpleTest.waitForExplicitFinish();
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+
+ ok("Test Plug-in" in navigator.plugins, "testplugin should be present");
+ ok("application/x-test" in navigator.mimeTypes, "testplugin MIME should be present");
+
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_DISABLED);
+ ok(!("Test Plug-in" in navigator.plugins), "testplugin should not be present");
+ ok(!("application/x-test" in navigator.mimeTypes), "testplugin MIME should not be present");
+
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ ok("Test Plug-in" in navigator.plugins, "testplugin should be present again");
+ ok("application/x-test" in navigator.mimeTypes, "testplugin MIME should be present again");
+ SimpleTest.finish();
+ </script>
+ </body>
+</html>