mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset 5747034f2bcc (bug 899347) for mochitest-bc failures.
CLOSED TREE
This commit is contained in:
parent
3778cb7fb2
commit
a0693c9204
File diff suppressed because it is too large
Load Diff
@ -258,6 +258,12 @@ XPCOMUtils.defineLazyGetter(this, "PageMenu", function() {
|
|||||||
*/
|
*/
|
||||||
function pageShowEventHandlers(persisted) {
|
function pageShowEventHandlers(persisted) {
|
||||||
XULBrowserWindow.asyncUpdateUI();
|
XULBrowserWindow.asyncUpdateUI();
|
||||||
|
|
||||||
|
// The PluginClickToPlay events are not fired when navigating using the
|
||||||
|
// BF cache. |persisted| is true when the page is loaded from the
|
||||||
|
// BF cache, so this code reshows the notification if necessary.
|
||||||
|
if (persisted)
|
||||||
|
gPluginHandler.reshowClickToPlayNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateBackForwardCommands(aWebNavigation) {
|
function UpdateBackForwardCommands(aWebNavigation) {
|
||||||
@ -774,6 +780,13 @@ var gBrowserInit = {
|
|||||||
|
|
||||||
gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
|
gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
|
||||||
|
|
||||||
|
// Note that the XBL binding is untrusted
|
||||||
|
gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
|
||||||
|
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
|
||||||
|
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
|
||||||
|
gBrowser.addEventListener("PluginInstantiated", gPluginHandler, true);
|
||||||
|
gBrowser.addEventListener("PluginRemoved", gPluginHandler, true);
|
||||||
|
|
||||||
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
|
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
|
||||||
|
|
||||||
Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false);
|
Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false);
|
||||||
|
@ -16,8 +16,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent",
|
|||||||
"resource://gre/modules/LoginManagerContent.jsm");
|
"resource://gre/modules/LoginManagerContent.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "InsecurePasswordUtils",
|
XPCOMUtils.defineLazyModuleGetter(this, "InsecurePasswordUtils",
|
||||||
"resource://gre/modules/InsecurePasswordUtils.jsm");
|
"resource://gre/modules/InsecurePasswordUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "PluginContent",
|
|
||||||
"resource:///modules/PluginContent.jsm");
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
|
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
|
||||||
@ -495,9 +493,6 @@ ClickEventHandler.init();
|
|||||||
|
|
||||||
ContentLinkHandler.init(this);
|
ContentLinkHandler.init(this);
|
||||||
|
|
||||||
// TODO: Load this lazily so the JSM is run only if a relevant event/message fires.
|
|
||||||
let pluginContent = new PluginContent(global);
|
|
||||||
|
|
||||||
addEventListener("DOMWebNotificationClicked", function(event) {
|
addEventListener("DOMWebNotificationClicked", function(event) {
|
||||||
sendAsyncMessage("DOMWebNotificationClicked", {});
|
sendAsyncMessage("DOMWebNotificationClicked", {});
|
||||||
}, false);
|
}, false);
|
||||||
|
@ -1315,11 +1315,11 @@ nsContextMenu.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
playPlugin: function() {
|
playPlugin: function() {
|
||||||
gPluginHandler.contextMenuCommand(this.browser, this.target, "play");
|
gPluginHandler._showClickToPlayNotification(this.browser, this.target, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
hidePlugin: function() {
|
hidePlugin: function() {
|
||||||
gPluginHandler.contextMenuCommand(this.browser, this.target, "hide");
|
gPluginHandler.hideClickToPlayOverlay(this.target);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Generate email address and put it on clipboard.
|
// Generate email address and put it on clipboard.
|
||||||
|
@ -8,72 +8,6 @@ const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browse
|
|||||||
const gTestRoot = getRootDirectory(gTestPath);
|
const gTestRoot = getRootDirectory(gTestPath);
|
||||||
var gTestBrowser = null;
|
var gTestBrowser = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* Frame script that will be injected into the test browser
|
|
||||||
* to cause the crash, and then manipulate the crashed plugin
|
|
||||||
* UI. Specifically, after the crash, we ensure that the
|
|
||||||
* crashed plugin UI is using the right style rules and that
|
|
||||||
* the submit URL opt-in defaults to checked. Then, we fill in
|
|
||||||
* a comment with the crash report, uncheck the submit URL
|
|
||||||
* opt-in, and send the crash reports.
|
|
||||||
*/
|
|
||||||
function frameScript() {
|
|
||||||
function fail(reason) {
|
|
||||||
sendAsyncMessage("test:crash-plugin:fail", {
|
|
||||||
reason: `Failure from frameScript: ${reason}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addMessageListener("test:crash-plugin", () => {
|
|
||||||
let doc = content.document;
|
|
||||||
|
|
||||||
addEventListener("PluginCrashed", (event) => {
|
|
||||||
let plugin = doc.getElementById("test");
|
|
||||||
if (!plugin) {
|
|
||||||
fail("Could not find plugin element");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let getUI = (anonid) => {
|
|
||||||
return doc.getAnonymousElementByAttribute(plugin, "anonid", anonid);
|
|
||||||
};
|
|
||||||
|
|
||||||
let style = content.getComputedStyle(getUI("pleaseSubmit"));
|
|
||||||
if (style.display != "block") {
|
|
||||||
fail("Submission UI visibility is not correct. Expected block, "
|
|
||||||
+ " got " + style.display);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getUI("submitComment").value = "a test comment";
|
|
||||||
if (!getUI("submitURLOptIn").checked) {
|
|
||||||
fail("URL opt-in should default to true.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getUI("submitURLOptIn").click();
|
|
||||||
getUI("submitButton").click();
|
|
||||||
});
|
|
||||||
|
|
||||||
let plugin = doc.getElementById("test");
|
|
||||||
try {
|
|
||||||
plugin.crash()
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addMessageListener("test:plugin-submit-status", () => {
|
|
||||||
let doc = content.document;
|
|
||||||
let plugin = doc.getElementById("test");
|
|
||||||
let submitStatusEl =
|
|
||||||
doc.getAnonymousElementByAttribute(plugin, "anonid", "submitStatus");
|
|
||||||
let submitStatus = submitStatusEl.getAttribute("status");
|
|
||||||
sendAsyncMessage("test:plugin-submit-status:result", {
|
|
||||||
submitStatus: submitStatus,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that plugin crash submissions still work properly after
|
// Test that plugin crash submissions still work properly after
|
||||||
// click-to-play activation.
|
// click-to-play activation.
|
||||||
|
|
||||||
@ -97,18 +31,14 @@ function test() {
|
|||||||
|
|
||||||
let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
|
let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
|
||||||
gTestBrowser = gBrowser.getBrowserForTab(tab);
|
gTestBrowser = gBrowser.getBrowserForTab(tab);
|
||||||
let mm = gTestBrowser.messageManager;
|
gTestBrowser.addEventListener("PluginCrashed", onCrash, false);
|
||||||
mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", false);
|
|
||||||
mm.addMessageListener("test:crash-plugin:fail", (message) => {
|
|
||||||
ok(false, message.data.reason);
|
|
||||||
});
|
|
||||||
|
|
||||||
gTestBrowser.addEventListener("load", onPageLoad, true);
|
gTestBrowser.addEventListener("load", onPageLoad, true);
|
||||||
Services.obs.addObserver(onSubmitStatus, "crash-report-status", false);
|
Services.obs.addObserver(onSubmitStatus, "crash-report-status", false);
|
||||||
|
|
||||||
registerCleanupFunction(function cleanUp() {
|
registerCleanupFunction(function cleanUp() {
|
||||||
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
|
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
|
||||||
env.set("MOZ_CRASHREPORTER_URL", serverURL);
|
env.set("MOZ_CRASHREPORTER_URL", serverURL);
|
||||||
|
gTestBrowser.removeEventListener("PluginCrashed", onCrash, false);
|
||||||
gTestBrowser.removeEventListener("load", onPageLoad, true);
|
gTestBrowser.removeEventListener("load", onPageLoad, true);
|
||||||
Services.obs.removeObserver(onSubmitStatus, "crash-report-status");
|
Services.obs.removeObserver(onSubmitStatus, "crash-report-status");
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
@ -140,8 +70,31 @@ function afterBindingAttached() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function pluginActivated() {
|
function pluginActivated() {
|
||||||
let mm = gTestBrowser.messageManager;
|
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||||
mm.sendAsyncMessage("test:crash-plugin");
|
try {
|
||||||
|
plugin.crash();
|
||||||
|
} catch (e) {
|
||||||
|
// The plugin crashed in the above call, an exception is expected.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCrash() {
|
||||||
|
try {
|
||||||
|
let plugin = gBrowser.contentDocument.getElementById("test");
|
||||||
|
let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin);
|
||||||
|
let style =
|
||||||
|
gBrowser.contentWindow.getComputedStyle(elt("pleaseSubmit"));
|
||||||
|
is(style.display, "block", "Submission UI visibility should be correct");
|
||||||
|
|
||||||
|
elt("submitComment").value = "a test comment";
|
||||||
|
is(elt("submitURLOptIn").checked, true, "URL opt-in should default to true");
|
||||||
|
EventUtils.synthesizeMouseAtCenter(elt("submitURLOptIn"), {}, gTestBrowser.contentWindow);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(elt("submitButton"), {}, gTestBrowser.contentWindow);
|
||||||
|
// And now wait for the submission status notification.
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
failWithException(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSubmitStatus(subj, topic, data) {
|
function onSubmitStatus(subj, topic, data) {
|
||||||
@ -175,23 +128,19 @@ function onSubmitStatus(subj, topic, data) {
|
|||||||
ok(val === undefined,
|
ok(val === undefined,
|
||||||
"URL should be absent from extra data when opt-in not checked");
|
"URL should be absent from extra data when opt-in not checked");
|
||||||
|
|
||||||
let submitStatus = null;
|
// Execute this later in case the event to change submitStatus has not
|
||||||
let mm = gTestBrowser.messageManager;
|
// have been dispatched yet.
|
||||||
mm.addMessageListener("test:plugin-submit-status:result", (message) => {
|
executeSoon(function () {
|
||||||
submitStatus = message.data.submitStatus;
|
let plugin = gBrowser.contentDocument.getElementById("test");
|
||||||
|
let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin);
|
||||||
|
is(elt("submitStatus").getAttribute("status"), data,
|
||||||
|
"submitStatus data should match");
|
||||||
});
|
});
|
||||||
|
|
||||||
mm.sendAsyncMessage("test:plugin-submit-status");
|
|
||||||
|
|
||||||
let condition = () => submitStatus;
|
|
||||||
waitForCondition(condition, () => {
|
|
||||||
is(submitStatus, data, "submitStatus data should match");
|
|
||||||
finish();
|
|
||||||
}, "Waiting for submitStatus to be reported from frame script");
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
failWithException(err);
|
failWithException(err);
|
||||||
}
|
}
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPropertyBagValue(bag, key) {
|
function getPropertyBagValue(bag, key) {
|
||||||
|
@ -29,11 +29,11 @@ function handleEvent() {
|
|||||||
|
|
||||||
function part1() {
|
function part1() {
|
||||||
gBrowser.selectedBrowser.removeEventListener("PluginBindingAttached", handleEvent);
|
gBrowser.selectedBrowser.removeEventListener("PluginBindingAttached", handleEvent);
|
||||||
waitForNotificationPopup("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");
|
||||||
gNextTest = part2;
|
|
||||||
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
|
gNextTest = part2;
|
||||||
gNewWindow.addEventListener("load", handleEvent, true);
|
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
|
||||||
});
|
gNewWindow.addEventListener("load", handleEvent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function part2() {
|
function part2() {
|
||||||
@ -62,10 +62,10 @@ function part4() {
|
|||||||
|
|
||||||
function part5() {
|
function part5() {
|
||||||
gBrowser.selectedBrowser.removeEventListener("PluginBindingAttached", handleEvent);
|
gBrowser.selectedBrowser.removeEventListener("PluginBindingAttached", handleEvent);
|
||||||
waitForNotificationPopup("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");
|
||||||
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
|
|
||||||
waitForFocus(part6, gNewWindow);
|
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
|
||||||
});
|
waitForFocus(part6, gNewWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
function part6() {
|
function part6() {
|
||||||
@ -92,10 +92,8 @@ function part8() {
|
|||||||
|
|
||||||
let plugin = gNewWindow.gBrowser.selectedBrowser.contentDocument.getElementById("test");
|
let plugin = gNewWindow.gBrowser.selectedBrowser.contentDocument.getElementById("test");
|
||||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||||
waitForCondition(() => objLoadingContent.activated, shutdown, "plugin should be activated now");
|
ok(objLoadingContent.activated, "plugin should be activated now");
|
||||||
}
|
|
||||||
|
|
||||||
function shutdown() {
|
|
||||||
gNewWindow.close();
|
gNewWindow.close();
|
||||||
gNewWindow = null;
|
gNewWindow = null;
|
||||||
finish();
|
finish();
|
||||||
|
@ -74,15 +74,13 @@ function test1() {
|
|||||||
let plugin = doc.getElementById("test");
|
let plugin = doc.getElementById("test");
|
||||||
ok(plugin, "Test 1, Found plugin in page");
|
ok(plugin, "Test 1, Found plugin in page");
|
||||||
|
|
||||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
ok(overlay.classList.contains("visible"), "Test 1, Plugin overlay should exist, not be hidden");
|
||||||
ok(overlay.classList.contains("visible"), "Test 1, Plugin overlay should exist, not be hidden");
|
let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon")
|
||||||
let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon");
|
|
||||||
|
|
||||||
EventUtils.synthesizeMouseAtCenter(closeIcon, {}, frame.contentWindow);
|
EventUtils.synthesizeMouseAtCenter(closeIcon, {}, frame.contentWindow);
|
||||||
let condition = () => !overlay.classList.contains("visible");
|
let condition = () => !overlay.classList.contains("visible");
|
||||||
waitForCondition(condition, test2, "Test 1, Waited too long for the overlay to become invisible.");
|
waitForCondition(condition, test2, "Test 1, Waited too long for the overlay to become invisible.");
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test2() {
|
function test2() {
|
||||||
|
@ -63,37 +63,43 @@ function runAfterPluginBindingAttached(func) {
|
|||||||
// Tests for the notification bar for hidden plugins.
|
// Tests for the notification bar for hidden plugins.
|
||||||
|
|
||||||
function test1() {
|
function test1() {
|
||||||
info("Test 1 - expecting a notification bar for hidden plugins.");
|
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
ok(notification, "Test 1: There should be a plugin notification");
|
||||||
waitForNotificationBar("plugin-hidden", gTestBrowser, () => {
|
|
||||||
|
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||||
|
|
||||||
|
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||||
|
() => {
|
||||||
// Don't use setTestPluginEnabledState here because we already saved the
|
// Don't use setTestPluginEnabledState here because we already saved the
|
||||||
// prior value
|
// prior value
|
||||||
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
||||||
prepareTest(test2, gTestRoot + "plugin_small.html");
|
prepareTest(test2, gTestRoot + "plugin_small.html");
|
||||||
});
|
},
|
||||||
});
|
"Test 1, expected to have a plugin notification bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
function test2() {
|
function test2() {
|
||||||
info("Test 2 - expecting no plugin notification bar on visible plugins.");
|
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
ok(notification, "Test 2: There should be a plugin notification");
|
||||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
|
||||||
|
|
||||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
|
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||||
() => {
|
|
||||||
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
|
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
|
||||||
prepareTest(test3, gTestRoot + "plugin_overlayed.html");
|
() => {
|
||||||
},
|
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
|
||||||
"expected to not have a plugin notification bar"
|
prepareTest(test3, gTestRoot + "plugin_overlayed.html");
|
||||||
);
|
},
|
||||||
});
|
"Test 2, expected to not have a plugin notification bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
function test3() {
|
function test3() {
|
||||||
info("Test 3 - expecting a plugin notification bar when plugins are overlaid");
|
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
ok(notification, "Test 3: There should be a plugin notification");
|
||||||
waitForNotificationBar("plugin-hidden", gTestBrowser, test3b);
|
|
||||||
});
|
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||||
|
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||||
|
test3b,
|
||||||
|
"Test 3, expected the plugin infobar to be triggered when plugin was overlayed");
|
||||||
}
|
}
|
||||||
|
|
||||||
function test3b()
|
function test3b()
|
||||||
@ -112,10 +118,13 @@ function test3b()
|
|||||||
}
|
}
|
||||||
|
|
||||||
function test4() {
|
function test4() {
|
||||||
info("Test 4 - expecting a plugin notification bar when plugins are overlaid offscreen")
|
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
ok(notification, "Test 4: There should be a plugin notification");
|
||||||
waitForNotificationBar("plugin-hidden", gTestBrowser, test4b);
|
|
||||||
});
|
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||||
|
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||||
|
test4b,
|
||||||
|
"Test 4, expected the plugin infobar to be triggered when plugin was overlayed");
|
||||||
}
|
}
|
||||||
|
|
||||||
function test4b() {
|
function test4b() {
|
||||||
@ -132,6 +141,9 @@ function test4b() {
|
|||||||
prepareTest(runAfterPluginBindingAttached(test5), gHttpTestRoot + "plugin_small.html");
|
prepareTest(runAfterPluginBindingAttached(test5), gHttpTestRoot + "plugin_small.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that the notification bar is getting dismissed when directly activating plugins
|
||||||
|
// via the doorhanger.
|
||||||
|
|
||||||
function test5() {
|
function test5() {
|
||||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||||
@ -139,27 +151,23 @@ function test5() {
|
|||||||
"Test 5, expected a notification bar for hidden plugins");
|
"Test 5, expected a notification bar for hidden plugins");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the notification bar is getting dismissed when directly activating plugins
|
|
||||||
// via the doorhanger.
|
|
||||||
|
|
||||||
function test6() {
|
function test6() {
|
||||||
info("Test 6 - expecting the doorhanger to be dismissed when directly activating plugins.");
|
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, (notification) => {
|
ok(notification, "Test 6, Should have a click-to-play notification");
|
||||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||||
ok(plugin, "Test 6, Found plugin in page");
|
ok(plugin, "Test 6, Found plugin in page");
|
||||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
|
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
|
||||||
"Test 6, Plugin should be click-to-play");
|
"Test 6, Plugin should be click-to-play");
|
||||||
|
|
||||||
// simulate "always allow"
|
// simulate "always allow"
|
||||||
notification.reshow();
|
notification.reshow();
|
||||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||||
|
|
||||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
|
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
|
||||||
test7,
|
test7,
|
||||||
"Test 6, expected the notification bar for hidden plugins to get dismissed");
|
"Test 6, expected the notification bar for hidden plugins to get dismissed");
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test7() {
|
function test7() {
|
||||||
|
@ -60,8 +60,10 @@ function test1b() {
|
|||||||
// Click the activate button on doorhanger to make sure it works
|
// Click the activate button on doorhanger to make sure it works
|
||||||
popupNotification.reshow();
|
popupNotification.reshow();
|
||||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||||
var condition = function() objLoadingContent.activated;
|
|
||||||
waitForCondition(condition, test1c, "Test 1b, Waited too long for plugin activation");
|
ok(objLoadingContent.activated, "Test 1b, Doorhanger should activate plugin");
|
||||||
|
|
||||||
|
test1c();
|
||||||
}
|
}
|
||||||
|
|
||||||
function test1c() {
|
function test1c() {
|
||||||
|
@ -36,14 +36,12 @@ function pluginBindingAttached() {
|
|||||||
ok(testplugin, "should have test plugin");
|
ok(testplugin, "should have test plugin");
|
||||||
var secondtestplugin = doc.getElementById("secondtest");
|
var secondtestplugin = doc.getElementById("secondtest");
|
||||||
ok(!secondtestplugin, "should not yet have second test plugin");
|
ok(!secondtestplugin, "should not yet have second test plugin");
|
||||||
var notification;
|
var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, (notification => {
|
ok(notification, "should have popup notification");
|
||||||
ok(notification, "should have popup notification");
|
// We don't set up the action list until the notification is shown
|
||||||
// We don't set up the action list until the notification is shown
|
notification.reshow();
|
||||||
notification.reshow();
|
is(notification.options.pluginData.size, 1, "should be 1 type of plugin in the popup notification");
|
||||||
is(notification.options.pluginData.size, 1, "should be 1 type of plugin in the popup notification");
|
XPCNativeWrapper.unwrap(gTestBrowser.contentWindow).addSecondPlugin();
|
||||||
XPCNativeWrapper.unwrap(gTestBrowser.contentWindow).addSecondPlugin();
|
|
||||||
}));
|
|
||||||
} else if (gNumPluginBindingsAttached == 2) {
|
} else if (gNumPluginBindingsAttached == 2) {
|
||||||
var doc = gTestBrowser.contentDocument;
|
var doc = gTestBrowser.contentDocument;
|
||||||
var testplugin = doc.getElementById("test");
|
var testplugin = doc.getElementById("test");
|
||||||
@ -53,8 +51,8 @@ function pluginBindingAttached() {
|
|||||||
var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||||
ok(notification, "should have popup notification");
|
ok(notification, "should have popup notification");
|
||||||
notification.reshow();
|
notification.reshow();
|
||||||
let condition = () => (notification.options.pluginData.size == 2);
|
is(notification.options.pluginData.size, 2, "should be 2 types of plugin in the popup notification");
|
||||||
waitForCondition(condition, finish, "Waited too long for 2 types of plugins in popup notification");
|
finish();
|
||||||
} else {
|
} else {
|
||||||
ok(false, "if we've gotten here, something is quite wrong");
|
ok(false, "if we've gotten here, something is quite wrong");
|
||||||
}
|
}
|
||||||
|
@ -59,11 +59,11 @@ function onCrash(event) {
|
|||||||
is (propVal, val, "Correct property in detail propBag: " + name + ".");
|
is (propVal, val, "Correct property in detail propBag: " + name + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForNotificationBar("plugin-crashed", gTestBrowser, (notification) => {
|
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
let notification = notificationBox.getNotificationWithValue("plugin-crashed");
|
||||||
ok(notification, "Infobar was shown.");
|
|
||||||
is(notification.priority, notificationBox.PRIORITY_WARNING_MEDIUM, "Correct priority.");
|
ok(notification, "Infobar was shown.");
|
||||||
is(notification.getAttribute("label"), "The GlobalTestPlugin plugin has crashed.", "Correct message.");
|
is(notification.priority, notificationBox.PRIORITY_WARNING_MEDIUM, "Correct priority.");
|
||||||
finish();
|
is(notification.getAttribute("label"), "The GlobalTestPlugin plugin has crashed.", "Correct message.");
|
||||||
});
|
finish();
|
||||||
}
|
}
|
||||||
|
@ -6,80 +6,9 @@ Cu.import("resource://gre/modules/CrashSubmit.jsm", this);
|
|||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
const CRASH_URL = "http://example.com/browser/browser/base/content/test/plugins/plugin_crashCommentAndURL.html";
|
const CRASH_URL = "http://example.com/browser/browser/base/content/test/plugins/plugin_crashCommentAndURL.html";
|
||||||
|
|
||||||
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
|
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
|
||||||
|
|
||||||
/**
|
|
||||||
* Frame script that will be injected into the test browser
|
|
||||||
* to cause plugin crashes, and then manipulate the crashed plugin
|
|
||||||
* UI. The specific actions and checks that occur in the frame
|
|
||||||
* script for the crashed plugin UI are set in the
|
|
||||||
* test:crash-plugin message object sent from the parent. The actions
|
|
||||||
* and checks that the parent can specify are:
|
|
||||||
*
|
|
||||||
* pleaseSubmitStyle: the display style that the pleaseSubmit anonymous element
|
|
||||||
* should have - example "block", "none".
|
|
||||||
* submitComment: the comment that should be put into the crash report
|
|
||||||
* urlOptIn: true if the submitURLOptIn element should be checked.
|
|
||||||
* sendCrashMessage: if true, the frame script will send a
|
|
||||||
* test:crash-plugin:crashed message when the plugin has
|
|
||||||
* crashed. This is used for the last test case, and
|
|
||||||
* causes the frame script to skip any of the crashed
|
|
||||||
* plugin UI manipulation, since the last test shows
|
|
||||||
* no crashed plugin UI.
|
|
||||||
*/
|
|
||||||
function frameScript() {
|
|
||||||
function fail(reason) {
|
|
||||||
sendAsyncMessage("test:crash-plugin:fail", {
|
|
||||||
reason: `Failure from frameScript: ${reason}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addMessageListener("test:crash-plugin", (message) => {
|
|
||||||
addEventListener("PluginCrashed", function onPluginCrashed(event) {
|
|
||||||
removeEventListener("PluginCrashed", onPluginCrashed);
|
|
||||||
|
|
||||||
let doc = content.document;
|
|
||||||
let plugin = doc.getElementById("plugin");
|
|
||||||
if (!plugin) {
|
|
||||||
fail("Could not find plugin element");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let getUI = (anonid) => {
|
|
||||||
return doc.getAnonymousElementByAttribute(plugin, "anonid", anonid);
|
|
||||||
};
|
|
||||||
|
|
||||||
let style = content.getComputedStyle(getUI("pleaseSubmit"));
|
|
||||||
if (style.display != message.data.pleaseSubmitStyle) {
|
|
||||||
fail("Submission UI visibility is not correct. Expected " +
|
|
||||||
`${message.data.pleaseSubmitStyle} and got ${style.display}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.data.sendCrashMessage) {
|
|
||||||
let propBag = event.detail.QueryInterface(Ci.nsIPropertyBag2);
|
|
||||||
let crashID = propBag.getPropertyAsAString("pluginDumpID");
|
|
||||||
sendAsyncMessage("test:crash-plugin:crashed", {
|
|
||||||
crashID: crashID,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.data.submitComment) {
|
|
||||||
getUI("submitComment").value = message.data.submitComment;
|
|
||||||
}
|
|
||||||
getUI("submitURLOptIn").checked = message.data.urlOptIn;
|
|
||||||
getUI("submitButton").click();
|
|
||||||
});
|
|
||||||
|
|
||||||
let plugin = content.document.getElementById("test");
|
|
||||||
try {
|
|
||||||
plugin.crash()
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
// Crashing the plugin takes up a lot of time, so extend the test timeout.
|
// Crashing the plugin takes up a lot of time, so extend the test timeout.
|
||||||
requestLongerTimeout(runs.length);
|
requestLongerTimeout(runs.length);
|
||||||
@ -100,18 +29,14 @@ function test() {
|
|||||||
|
|
||||||
let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
|
let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
|
||||||
let browser = gBrowser.getBrowserForTab(tab);
|
let browser = gBrowser.getBrowserForTab(tab);
|
||||||
let mm = browser.messageManager;
|
browser.addEventListener("PluginCrashed", onCrash, false);
|
||||||
mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
|
|
||||||
|
|
||||||
mm.addMessageListener("test:crash-plugin:fail", (message) => {
|
|
||||||
ok(false, message.data.reason);
|
|
||||||
});
|
|
||||||
|
|
||||||
Services.obs.addObserver(onSubmitStatus, "crash-report-status", false);
|
Services.obs.addObserver(onSubmitStatus, "crash-report-status", false);
|
||||||
|
|
||||||
registerCleanupFunction(function cleanUp() {
|
registerCleanupFunction(function cleanUp() {
|
||||||
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
|
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
|
||||||
env.set("MOZ_CRASHREPORTER_URL", serverURL);
|
env.set("MOZ_CRASHREPORTER_URL", serverURL);
|
||||||
|
gBrowser.selectedBrowser.removeEventListener("PluginCrashed", onCrash,
|
||||||
|
false);
|
||||||
Services.obs.removeObserver(onSubmitStatus, "crash-report-status");
|
Services.obs.removeObserver(onSubmitStatus, "crash-report-status");
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
});
|
});
|
||||||
@ -151,24 +76,6 @@ function doNextRun() {
|
|||||||
memo[arg] = currentRun[arg];
|
memo[arg] = currentRun[arg];
|
||||||
return memo;
|
return memo;
|
||||||
}, {});
|
}, {});
|
||||||
let mm = gBrowser.selectedBrowser.messageManager;
|
|
||||||
|
|
||||||
if (!currentRun.shouldSubmittionUIBeVisible) {
|
|
||||||
mm.addMessageListener("test:crash-plugin:crash", function onCrash(message) {
|
|
||||||
mm.removeMessageListener("test:crash-plugin:crash", onCrash);
|
|
||||||
|
|
||||||
ok(!!message.data.crashID, "pluginDumpID should be set");
|
|
||||||
CrashSubmit.delete(message.data.crashID);
|
|
||||||
doNextRun();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
mm.sendAsyncMessage("test:crash-plugin", {
|
|
||||||
pleaseSubmitStyle: currentRun.shouldSubmissionUIBeVisible ? "block" : "none",
|
|
||||||
submitComment: currentRun.comment,
|
|
||||||
urlOptIn: currentRun.urlOptIn,
|
|
||||||
sendOnCrashMessage: !currentRun.shouldSubmissionUIBeVisible,
|
|
||||||
});
|
|
||||||
gBrowser.loadURI(CRASH_URL + "?" +
|
gBrowser.loadURI(CRASH_URL + "?" +
|
||||||
encodeURIComponent(JSON.stringify(args)));
|
encodeURIComponent(JSON.stringify(args)));
|
||||||
// And now wait for the crash.
|
// And now wait for the crash.
|
||||||
@ -179,6 +86,37 @@ function doNextRun() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCrash(event) {
|
||||||
|
try {
|
||||||
|
let plugin = gBrowser.contentDocument.getElementById("plugin");
|
||||||
|
let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin);
|
||||||
|
let style =
|
||||||
|
gBrowser.contentWindow.getComputedStyle(elt("pleaseSubmit"));
|
||||||
|
is(style.display,
|
||||||
|
currentRun.shouldSubmissionUIBeVisible ? "block" : "none",
|
||||||
|
"Submission UI visibility should be correct");
|
||||||
|
if (!currentRun.shouldSubmissionUIBeVisible) {
|
||||||
|
// Done with this run. We don't submit the crash, so we will have to
|
||||||
|
// remove the dump manually.
|
||||||
|
let propBag = event.detail.QueryInterface(Ci.nsIPropertyBag2);
|
||||||
|
let crashID = propBag.getPropertyAsAString("pluginDumpID");
|
||||||
|
ok(!!crashID, "pluginDumpID should be set");
|
||||||
|
CrashSubmit.delete(crashID);
|
||||||
|
|
||||||
|
doNextRun();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
elt("submitComment").value = currentRun.comment;
|
||||||
|
elt("submitURLOptIn").checked = currentRun.urlOptIn;
|
||||||
|
elt("submitButton").click();
|
||||||
|
// And now wait for the submission status notification.
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
failWithException(err);
|
||||||
|
doNextRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onSubmitStatus(subj, topic, data) {
|
function onSubmitStatus(subj, topic, data) {
|
||||||
try {
|
try {
|
||||||
// Wait for success or failed, doesn't matter which.
|
// Wait for success or failed, doesn't matter which.
|
||||||
|
@ -56,7 +56,6 @@ TabOpenListener.prototype = {
|
|||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
SimpleTest.requestCompleteLog();
|
|
||||||
requestLongerTimeout(2);
|
requestLongerTimeout(2);
|
||||||
registerCleanupFunction(function() {
|
registerCleanupFunction(function() {
|
||||||
clearAllPluginPermissions();
|
clearAllPluginPermissions();
|
||||||
@ -798,10 +797,7 @@ function test24a() {
|
|||||||
// simulate "always allow"
|
// simulate "always allow"
|
||||||
notification.reshow();
|
notification.reshow();
|
||||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||||
waitForCondition(() => objLoadingContent.activated, () => {
|
prepareTest(test24b, gHttpTestRoot + "plugin_test.html");
|
||||||
prepareTest(test24b, gHttpTestRoot + "plugin_test.html");
|
|
||||||
}, "Test 24a, plugin should now be activated.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// did the "always allow" work as intended?
|
// did the "always allow" work as intended?
|
||||||
@ -809,11 +805,11 @@ function test24b() {
|
|||||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||||
ok(plugin, "Test 24b, Found plugin in page");
|
ok(plugin, "Test 24b, Found plugin in page");
|
||||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||||
waitForCondition(() => objLoadingContent.activated, () => {
|
ok(objLoadingContent.activated, "Test 24b, plugin should be activated");
|
||||||
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml", () => {
|
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
|
||||||
prepareTest(runAfterPluginBindingAttached(test24c), gHttpTestRoot + "plugin_test.html");
|
function() {
|
||||||
});
|
prepareTest(runAfterPluginBindingAttached(test24c), gHttpTestRoot + "plugin_test.html");
|
||||||
}, "Test 24b, plugin should be activated");
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// the plugin is now blocklisted, so it should not automatically load
|
// the plugin is now blocklisted, so it should not automatically load
|
||||||
@ -824,13 +820,13 @@ function test24c() {
|
|||||||
ok(plugin, "Test 24c, Found plugin in page");
|
ok(plugin, "Test 24c, Found plugin in page");
|
||||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "Test 24c, Plugin should be vulnerable/updatable");
|
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "Test 24c, Plugin should be vulnerable/updatable");
|
||||||
waitForCondition(() => !objLoadingContent.activated, () => {
|
ok(!objLoadingContent.activated, "Test 24c, plugin should not be activated");
|
||||||
// simulate "always allow"
|
|
||||||
notification.reshow();
|
|
||||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
|
||||||
|
|
||||||
prepareTest(test24d, gHttpTestRoot + "plugin_test.html");
|
// simulate "always allow"
|
||||||
}, "Test 24c, plugin should not be activated");
|
notification.reshow();
|
||||||
|
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||||
|
|
||||||
|
prepareTest(test24d, gHttpTestRoot + "plugin_test.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should still be able to always allow a plugin after we've seen that it's
|
// We should still be able to always allow a plugin after we've seen that it's
|
||||||
@ -839,14 +835,15 @@ function test24d() {
|
|||||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||||
ok(plugin, "Test 24d, Found plugin in page");
|
ok(plugin, "Test 24d, Found plugin in page");
|
||||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||||
waitForCondition(() => objLoadingContent.activated, () => {
|
ok(objLoadingContent.activated, "Test 24d, plugin should be activated");
|
||||||
// this resets the vulnerable plugin permission
|
|
||||||
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", () => {
|
// this resets the vulnerable plugin permission
|
||||||
clearAllPluginPermissions();
|
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml",
|
||||||
resetBlocklist();
|
function() {
|
||||||
prepareTest(test25, gTestRoot + "plugin_syncRemoved.html");
|
clearAllPluginPermissions();
|
||||||
});
|
resetBlocklist();
|
||||||
}, "Test 24d, plugin should be activated");
|
prepareTest(test25, gTestRoot + "plugin_syncRemoved.html");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function test25() {
|
function test25() {
|
||||||
|
@ -108,28 +108,3 @@ function setAndUpdateBlocklist(aURL, aCallback) {
|
|||||||
function resetBlocklist() {
|
function resetBlocklist() {
|
||||||
Services.prefs.setCharPref("extensions.blocklist.url", _originalTestBlocklistURL);
|
Services.prefs.setCharPref("extensions.blocklist.url", _originalTestBlocklistURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitForNotificationPopup(notificationID, browser, callback) {
|
|
||||||
let notification;
|
|
||||||
waitForCondition(
|
|
||||||
() => (notification = PopupNotifications.getNotification(notificationID, browser)),
|
|
||||||
() => {
|
|
||||||
ok(notification, `Successfully got the ${notificationID} notification popup`);
|
|
||||||
callback(notification);
|
|
||||||
},
|
|
||||||
`Waited too long for the ${notificationID} notification popup`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitForNotificationBar(notificationID, browser, callback) {
|
|
||||||
let notification;
|
|
||||||
let notificationBox = gBrowser.getNotificationBox(browser);
|
|
||||||
waitForCondition(
|
|
||||||
() => (notification = notificationBox.getNotificationWithValue(notificationID)),
|
|
||||||
() => {
|
|
||||||
ok(notification, `Successfully got the ${notificationID} notification bar`);
|
|
||||||
callback(notification);
|
|
||||||
},
|
|
||||||
`Waited too long for the ${notificationID} notification bar`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
@ -1976,7 +1976,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let host = this.notification.options.host;
|
let host = gPluginHandler._getHostFromPrincipal(this.notification.browser.contentWindow.document.nodePrincipal);
|
||||||
this._setupDescription("pluginActivateMultiple.message", null, host);
|
this._setupDescription("pluginActivateMultiple.message", null, host);
|
||||||
|
|
||||||
var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox");
|
var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox");
|
||||||
|
@ -1,992 +0,0 @@
|
|||||||
# -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
let Cc = Components.classes;
|
|
||||||
let Ci = Components.interfaces;
|
|
||||||
let Cu = Components.utils;
|
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = [ "PluginContent" ];
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
Cu.import("resource://gre/modules/Timer.jsm");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "gNavigatorBundle", function() {
|
|
||||||
const url = "chrome://browser/locale/browser.properties";
|
|
||||||
return Services.strings.createBundle(url);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.PluginContent = function (global) {
|
|
||||||
this.init(global);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginContent.prototype = {
|
|
||||||
init: function (global) {
|
|
||||||
this.global = global;
|
|
||||||
// Need to hold onto the content window or else it'll get destroyed
|
|
||||||
this.content = this.global.content;
|
|
||||||
// Cache of plugin actions for the current page.
|
|
||||||
this.pluginData = new Map();
|
|
||||||
|
|
||||||
// Note that the XBL binding is untrusted
|
|
||||||
global.addEventListener("PluginBindingAttached", this, true, true);
|
|
||||||
global.addEventListener("PluginCrashed", this, true);
|
|
||||||
global.addEventListener("PluginOutdated", this, true);
|
|
||||||
global.addEventListener("PluginInstantiated", this, true);
|
|
||||||
global.addEventListener("PluginRemoved", this, true);
|
|
||||||
global.addEventListener("unload", this);
|
|
||||||
|
|
||||||
global.addEventListener("pageshow", (event) => this.onPageShow(event), true);
|
|
||||||
|
|
||||||
global.addMessageListener("BrowserPlugins:ActivatePlugins", this);
|
|
||||||
global.addMessageListener("BrowserPlugins:NotificationRemoved", this);
|
|
||||||
global.addMessageListener("BrowserPlugins:NotificationShown", this);
|
|
||||||
global.addMessageListener("BrowserPlugins:ContextMenuCommand", this);
|
|
||||||
},
|
|
||||||
|
|
||||||
uninit: function() {
|
|
||||||
delete this.global;
|
|
||||||
delete this.content;
|
|
||||||
},
|
|
||||||
|
|
||||||
receiveMessage: function (msg) {
|
|
||||||
switch (msg.name) {
|
|
||||||
case "BrowserPlugins:ActivatePlugins":
|
|
||||||
this.activatePlugins(msg.data.pluginInfo, msg.data.newState);
|
|
||||||
break;
|
|
||||||
case "BrowserPlugins:NotificationRemoved":
|
|
||||||
this.clearPluginDataCache();
|
|
||||||
break;
|
|
||||||
case "BrowserPlugins:NotificationShown":
|
|
||||||
setTimeout(() => this.updateNotificationUI(), 0);
|
|
||||||
break;
|
|
||||||
case "BrowserPlugins:ContextMenuCommand":
|
|
||||||
switch (msg.data.command) {
|
|
||||||
case "play":
|
|
||||||
this._showClickToPlayNotification(msg.objects.plugin, true);
|
|
||||||
break;
|
|
||||||
case "hide":
|
|
||||||
this.hideClickToPlayOverlay(msg.objects.plugin);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onPageShow: function (event) {
|
|
||||||
// Ignore events that aren't from the main document.
|
|
||||||
if (this.global.content && event.target != this.global.content.document) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The PluginClickToPlay events are not fired when navigating using the
|
|
||||||
// BF cache. |persisted| is true when the page is loaded from the
|
|
||||||
// BF cache, so this code reshows the notification if necessary.
|
|
||||||
if (event.persisted) {
|
|
||||||
this.reshowClickToPlayNotification();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getPluginUI: function (plugin, anonid) {
|
|
||||||
return plugin.ownerDocument.
|
|
||||||
getAnonymousElementByAttribute(plugin, "anonid", anonid);
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPluginInfo: function (pluginElement) {
|
|
||||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
|
||||||
pluginElement.QueryInterface(Ci.nsIObjectLoadingContent);
|
|
||||||
|
|
||||||
let tagMimetype;
|
|
||||||
let pluginName = gNavigatorBundle.GetStringFromName("pluginInfo.unknownPlugin");
|
|
||||||
let pluginTag = null;
|
|
||||||
let permissionString = null;
|
|
||||||
let fallbackType = null;
|
|
||||||
let blocklistState = null;
|
|
||||||
|
|
||||||
tagMimetype = pluginElement.actualType;
|
|
||||||
if (tagMimetype == "") {
|
|
||||||
tagMimetype = pluginElement.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isKnownPlugin(pluginElement)) {
|
|
||||||
pluginTag = pluginHost.getPluginTagForType(pluginElement.actualType);
|
|
||||||
pluginName = this.makeNicePluginName(pluginTag.name);
|
|
||||||
|
|
||||||
permissionString = pluginHost.getPermissionStringForType(pluginElement.actualType);
|
|
||||||
fallbackType = pluginElement.defaultFallbackType;
|
|
||||||
blocklistState = pluginHost.getBlocklistStateForType(pluginElement.actualType);
|
|
||||||
// Make state-softblocked == state-notblocked for our purposes,
|
|
||||||
// they have the same UI. STATE_OUTDATED should not exist for plugin
|
|
||||||
// items, but let's alias it anyway, just in case.
|
|
||||||
if (blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED ||
|
|
||||||
blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
|
|
||||||
blocklistState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { mimetype: tagMimetype,
|
|
||||||
pluginName: pluginName,
|
|
||||||
pluginTag: pluginTag,
|
|
||||||
permissionString: permissionString,
|
|
||||||
fallbackType: fallbackType,
|
|
||||||
blocklistState: blocklistState,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
// Map the plugin's name to a filtered version more suitable for user UI.
|
|
||||||
makeNicePluginName : function (aName) {
|
|
||||||
if (aName == "Shockwave Flash")
|
|
||||||
return "Adobe Flash";
|
|
||||||
|
|
||||||
// Clean up the plugin name by stripping off parenthetical clauses,
|
|
||||||
// trailing version numbers or "plugin".
|
|
||||||
// EG, "Foo Bar (Linux) Plugin 1.23_02" --> "Foo Bar"
|
|
||||||
// Do this by first stripping the numbers, etc. off the end, and then
|
|
||||||
// removing "Plugin" (and then trimming to get rid of any whitespace).
|
|
||||||
// (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled)
|
|
||||||
let newName = aName.replace(/\(.*?\)/g, "").
|
|
||||||
replace(/[\s\d\.\-\_\(\)]+$/, "").
|
|
||||||
replace(/\bplug-?in\b/i, "").trim();
|
|
||||||
return newName;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the visibility of the plugin overlay.
|
|
||||||
*/
|
|
||||||
setVisibility : function (plugin, overlay, shouldShow) {
|
|
||||||
overlay.classList.toggle("visible", shouldShow);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the plugin should be visible on the page. A plugin should
|
|
||||||
* not be visible if the overlay is too big, or if any other page content
|
|
||||||
* overlays it.
|
|
||||||
*
|
|
||||||
* This function will handle showing or hiding the overlay.
|
|
||||||
* @returns true if the plugin is invisible.
|
|
||||||
*/
|
|
||||||
shouldShowOverlay : function (plugin, overlay) {
|
|
||||||
// If the overlay size is 0, we haven't done layout yet. Presume that
|
|
||||||
// plugins are visible until we know otherwise.
|
|
||||||
if (overlay.scrollWidth == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the <object>'s size too small to hold what we want to show?
|
|
||||||
let pluginRect = plugin.getBoundingClientRect();
|
|
||||||
// XXX bug 446693. The text-shadow on the submitted-report text at
|
|
||||||
// the bottom causes scrollHeight to be larger than it should be.
|
|
||||||
let overflows = (overlay.scrollWidth > Math.ceil(pluginRect.width)) ||
|
|
||||||
(overlay.scrollHeight - 5 > Math.ceil(pluginRect.height));
|
|
||||||
if (overflows) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the plugin covered up by other content so that it is not clickable?
|
|
||||||
// Floating point can confuse .elementFromPoint, so inset just a bit
|
|
||||||
let left = pluginRect.left + 2;
|
|
||||||
let right = pluginRect.right - 2;
|
|
||||||
let top = pluginRect.top + 2;
|
|
||||||
let bottom = pluginRect.bottom - 2;
|
|
||||||
let centerX = left + (right - left) / 2;
|
|
||||||
let centerY = top + (bottom - top) / 2;
|
|
||||||
let points = [[left, top],
|
|
||||||
[left, bottom],
|
|
||||||
[right, top],
|
|
||||||
[right, bottom],
|
|
||||||
[centerX, centerY]];
|
|
||||||
|
|
||||||
if (right <= 0 || top <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let contentWindow = plugin.ownerDocument.defaultView;
|
|
||||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
|
||||||
|
|
||||||
for (let [x, y] of points) {
|
|
||||||
let el = cwu.elementFromPoint(x, y, true, true);
|
|
||||||
if (el !== plugin) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
addLinkClickCallback: function (linkNode, callbackName /*callbackArgs...*/) {
|
|
||||||
// XXX just doing (callback)(arg) was giving a same-origin error. bug?
|
|
||||||
let self = this;
|
|
||||||
let callbackArgs = Array.prototype.slice.call(arguments).slice(2);
|
|
||||||
linkNode.addEventListener("click",
|
|
||||||
function(evt) {
|
|
||||||
if (!evt.isTrusted)
|
|
||||||
return;
|
|
||||||
evt.preventDefault();
|
|
||||||
if (callbackArgs.length == 0)
|
|
||||||
callbackArgs = [ evt ];
|
|
||||||
(self[callbackName]).apply(self, callbackArgs);
|
|
||||||
},
|
|
||||||
true);
|
|
||||||
|
|
||||||
linkNode.addEventListener("keydown",
|
|
||||||
function(evt) {
|
|
||||||
if (!evt.isTrusted)
|
|
||||||
return;
|
|
||||||
if (evt.keyCode == evt.DOM_VK_RETURN) {
|
|
||||||
evt.preventDefault();
|
|
||||||
if (callbackArgs.length == 0)
|
|
||||||
callbackArgs = [ evt ];
|
|
||||||
evt.preventDefault();
|
|
||||||
(self[callbackName]).apply(self, callbackArgs);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
true);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Helper to get the binding handler type from a plugin object
|
|
||||||
_getBindingType : function(plugin) {
|
|
||||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
switch (plugin.pluginFallbackType) {
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED:
|
|
||||||
return "PluginNotFound";
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_DISABLED:
|
|
||||||
return "PluginDisabled";
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED:
|
|
||||||
return "PluginBlocklisted";
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_OUTDATED:
|
|
||||||
return "PluginOutdated";
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
|
|
||||||
return "PluginClickToPlay";
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
|
|
||||||
return "PluginVulnerableUpdatable";
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
|
|
||||||
return "PluginVulnerableNoUpdate";
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
|
|
||||||
return "PluginPlayPreview";
|
|
||||||
default:
|
|
||||||
// Not all states map to a handler
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEvent: function (event) {
|
|
||||||
let eventType = event.type;
|
|
||||||
|
|
||||||
if (eventType == "unload") {
|
|
||||||
this.uninit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventType == "PluginRemoved") {
|
|
||||||
this.updateNotificationUI();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventType == "click") {
|
|
||||||
this.onOverlayClick(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventType == "PluginCrashed" &&
|
|
||||||
!(event.target instanceof Ci.nsIObjectLoadingContent)) {
|
|
||||||
// If the event target is not a plugin object (i.e., an <object> or
|
|
||||||
// <embed> element), this call is for a window-global plugin.
|
|
||||||
this.pluginInstanceCrashed(event.target, event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let plugin = event.target;
|
|
||||||
let doc = plugin.ownerDocument;
|
|
||||||
|
|
||||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (eventType == "PluginBindingAttached") {
|
|
||||||
// The plugin binding fires this event when it is created.
|
|
||||||
// As an untrusted event, ensure that this object actually has a binding
|
|
||||||
// and make sure we don't handle it twice
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
if (!overlay || overlay._bindingHandled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
overlay._bindingHandled = true;
|
|
||||||
|
|
||||||
// Lookup the handler for this binding
|
|
||||||
eventType = this._getBindingType(plugin);
|
|
||||||
if (!eventType) {
|
|
||||||
// Not all bindings have handlers
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let shouldShowNotification = false;
|
|
||||||
switch (eventType) {
|
|
||||||
case "PluginCrashed":
|
|
||||||
this.pluginInstanceCrashed(plugin, event);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "PluginNotFound": {
|
|
||||||
let installable = this.showInstallNotification(plugin, eventType);
|
|
||||||
let contentWindow = plugin.ownerDocument.defaultView;
|
|
||||||
// For non-object plugin tags, register a click handler to install the
|
|
||||||
// plugin. Object tags can, and often do, deal with that themselves,
|
|
||||||
// so don't stomp on the page developers toes.
|
|
||||||
if (installable && !(plugin instanceof contentWindow.HTMLObjectElement)) {
|
|
||||||
let installStatus = this.getPluginUI(plugin, "installStatus");
|
|
||||||
installStatus.setAttribute("installable", "true");
|
|
||||||
let iconStatus = this.getPluginUI(plugin, "icon");
|
|
||||||
iconStatus.setAttribute("installable", "true");
|
|
||||||
|
|
||||||
let installLink = this.getPluginUI(plugin, "installPluginLink");
|
|
||||||
this.addLinkClickCallback(installLink, "installSinglePlugin", plugin);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "PluginBlocklisted":
|
|
||||||
case "PluginOutdated":
|
|
||||||
shouldShowNotification = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "PluginVulnerableUpdatable":
|
|
||||||
let updateLink = this.getPluginUI(plugin, "checkForUpdatesLink");
|
|
||||||
this.addLinkClickCallback(updateLink, "forwardCallback", "openPluginUpdatePage");
|
|
||||||
/* FALLTHRU */
|
|
||||||
|
|
||||||
case "PluginVulnerableNoUpdate":
|
|
||||||
case "PluginClickToPlay":
|
|
||||||
this._handleClickToPlayEvent(plugin);
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
let pluginName = this._getPluginInfo(plugin).pluginName;
|
|
||||||
let messageString = gNavigatorBundle.formatStringFromName("PluginClickToActivate", [pluginName], 1);
|
|
||||||
let overlayText = this.getPluginUI(plugin, "clickToPlay");
|
|
||||||
overlayText.textContent = messageString;
|
|
||||||
if (eventType == "PluginVulnerableUpdatable" ||
|
|
||||||
eventType == "PluginVulnerableNoUpdate") {
|
|
||||||
let vulnerabilityString = gNavigatorBundle.GetStringFromName(eventType);
|
|
||||||
let vulnerabilityText = this.getPluginUI(plugin, "vulnerabilityStatus");
|
|
||||||
vulnerabilityText.textContent = vulnerabilityString;
|
|
||||||
}
|
|
||||||
shouldShowNotification = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "PluginPlayPreview":
|
|
||||||
this._handlePlayPreviewEvent(plugin);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "PluginDisabled":
|
|
||||||
let manageLink = this.getPluginUI(plugin, "managePluginsLink");
|
|
||||||
this.addLinkClickCallback(manageLink, "forwardCallback", "managePlugins");
|
|
||||||
shouldShowNotification = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "PluginInstantiated":
|
|
||||||
shouldShowNotification = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show the in-content UI if it's not too big. The crashed plugin handler already did this.
|
|
||||||
if (eventType != "PluginCrashed") {
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
if (overlay != null) {
|
|
||||||
this.setVisibility(plugin, overlay,
|
|
||||||
this.shouldShowOverlay(plugin, overlay));
|
|
||||||
let resizeListener = (event) => {
|
|
||||||
this.setVisibility(plugin, overlay,
|
|
||||||
this.shouldShowOverlay(plugin, overlay));
|
|
||||||
this.updateNotificationUI();
|
|
||||||
};
|
|
||||||
plugin.addEventListener("overflow", resizeListener);
|
|
||||||
plugin.addEventListener("underflow", resizeListener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let closeIcon = this.getPluginUI(plugin, "closeIcon");
|
|
||||||
if (closeIcon) {
|
|
||||||
closeIcon.addEventListener("click", event => {
|
|
||||||
if (event.button == 0 && event.isTrusted)
|
|
||||||
this.hideClickToPlayOverlay(plugin);
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldShowNotification) {
|
|
||||||
this._showClickToPlayNotification(plugin, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isKnownPlugin: function (objLoadingContent) {
|
|
||||||
return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
|
|
||||||
Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
|
||||||
},
|
|
||||||
|
|
||||||
canActivatePlugin: function (objLoadingContent) {
|
|
||||||
// if this isn't a known plugin, we can't activate it
|
|
||||||
// (this also guards pluginHost.getPermissionStringForType against
|
|
||||||
// unexpected input)
|
|
||||||
if (!this.isKnownPlugin(objLoadingContent))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
|
||||||
let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
|
|
||||||
let principal = objLoadingContent.ownerDocument.defaultView.top.document.nodePrincipal;
|
|
||||||
let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString);
|
|
||||||
|
|
||||||
let isFallbackTypeValid =
|
|
||||||
objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
|
|
||||||
objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
|
|
||||||
|
|
||||||
if (objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW) {
|
|
||||||
// checking if play preview is subject to CTP rules
|
|
||||||
let playPreviewInfo = pluginHost.getPlayPreviewInfo(objLoadingContent.actualType);
|
|
||||||
isFallbackTypeValid = !playPreviewInfo.ignoreCTP;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !objLoadingContent.activated &&
|
|
||||||
pluginPermission != Ci.nsIPermissionManager.DENY_ACTION &&
|
|
||||||
isFallbackTypeValid;
|
|
||||||
},
|
|
||||||
|
|
||||||
hideClickToPlayOverlay: function (plugin) {
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
if (overlay) {
|
|
||||||
overlay.classList.remove("visible");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
stopPlayPreview: function (plugin, playPlugin) {
|
|
||||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
|
||||||
if (objLoadingContent.activated)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (playPlugin)
|
|
||||||
objLoadingContent.playPlugin();
|
|
||||||
else
|
|
||||||
objLoadingContent.cancelPlayPreview();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Callback for user clicking on a missing (unsupported) plugin.
|
|
||||||
installSinglePlugin: function (plugin) {
|
|
||||||
this.global.sendAsyncMessage("PluginContent:InstallSinglePlugin", {
|
|
||||||
pluginInfo: this._getPluginInfo(plugin),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Forward a link click callback to the chrome process.
|
|
||||||
forwardCallback: function (name) {
|
|
||||||
this.global.sendAsyncMessage("PluginContent:LinkClickCallback", { name: name });
|
|
||||||
},
|
|
||||||
|
|
||||||
#ifdef MOZ_CRASHREPORTER
|
|
||||||
submitReport: function submitReport(pluginDumpID, browserDumpID, plugin) {
|
|
||||||
let keyVals = {};
|
|
||||||
if (plugin) {
|
|
||||||
let userComment = this.getPluginUI(plugin, "submitComment").value.trim();
|
|
||||||
if (userComment)
|
|
||||||
keyVals.PluginUserComment = userComment;
|
|
||||||
if (this.getPluginUI(plugin, "submitURLOptIn").checked)
|
|
||||||
keyVals.PluginContentURL = plugin.ownerDocument.URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.global.sendAsyncMessage("PluginContent:SubmitReport", {
|
|
||||||
pluginDumpID: pluginDumpID,
|
|
||||||
browserDumpID: browserDumpID,
|
|
||||||
keyVals: keyVals,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
#endif
|
|
||||||
|
|
||||||
reloadPage: function () {
|
|
||||||
this.global.content.location.reload();
|
|
||||||
},
|
|
||||||
|
|
||||||
showInstallNotification: function (plugin) {
|
|
||||||
let [shown] = this.global.sendSyncMessage("PluginContent:ShowInstallNotification", {
|
|
||||||
pluginInfo: this._getPluginInfo(plugin),
|
|
||||||
});
|
|
||||||
return shown;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Event listener for click-to-play plugins.
|
|
||||||
_handleClickToPlayEvent: function (plugin) {
|
|
||||||
let doc = plugin.ownerDocument;
|
|
||||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
|
||||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
|
||||||
// guard against giving pluginHost.getPermissionStringForType a type
|
|
||||||
// not associated with any known plugin
|
|
||||||
if (!this.isKnownPlugin(objLoadingContent))
|
|
||||||
return;
|
|
||||||
let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
|
|
||||||
let principal = doc.defaultView.top.document.nodePrincipal;
|
|
||||||
let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString);
|
|
||||||
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
|
|
||||||
if (pluginPermission == Ci.nsIPermissionManager.DENY_ACTION) {
|
|
||||||
if (overlay) {
|
|
||||||
overlay.classList.remove("visible");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overlay) {
|
|
||||||
overlay.addEventListener("click", this, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onOverlayClick: function (event) {
|
|
||||||
let document = event.target.ownerDocument;
|
|
||||||
let plugin = document.getBindingParent(event.target);
|
|
||||||
let contentWindow = plugin.ownerDocument.defaultView.top;
|
|
||||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
|
||||||
// Have to check that the target is not the link to update the plugin
|
|
||||||
if (!(event.originalTarget instanceof contentWindow.HTMLAnchorElement) &&
|
|
||||||
(event.originalTarget.getAttribute('anonid') != 'closeIcon') &&
|
|
||||||
event.button == 0 && event.isTrusted) {
|
|
||||||
this._showClickToPlayNotification(plugin, true);
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_handlePlayPreviewEvent: function (plugin) {
|
|
||||||
let doc = plugin.ownerDocument;
|
|
||||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
|
||||||
let pluginInfo = this._getPluginInfo(plugin);
|
|
||||||
let playPreviewInfo = pluginHost.getPlayPreviewInfo(pluginInfo.mimetype);
|
|
||||||
|
|
||||||
let previewContent = this.getPluginUI(plugin, "previewPluginContent");
|
|
||||||
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
|
|
||||||
if (!iframe) {
|
|
||||||
// lazy initialization of the iframe
|
|
||||||
iframe = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
|
|
||||||
iframe.className = "previewPluginContentFrame";
|
|
||||||
previewContent.appendChild(iframe);
|
|
||||||
|
|
||||||
// Force a style flush, so that we ensure our binding is attached.
|
|
||||||
plugin.clientTop;
|
|
||||||
}
|
|
||||||
iframe.src = playPreviewInfo.redirectURL;
|
|
||||||
|
|
||||||
// MozPlayPlugin event can be dispatched from the extension chrome
|
|
||||||
// code to replace the preview content with the native plugin
|
|
||||||
let playPluginHandler = (event) => {
|
|
||||||
if (!event.isTrusted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true);
|
|
||||||
|
|
||||||
let playPlugin = !event.detail;
|
|
||||||
this.stopPlayPreview(plugin, playPlugin);
|
|
||||||
|
|
||||||
// cleaning up: removes overlay iframe from the DOM
|
|
||||||
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
|
|
||||||
if (iframe)
|
|
||||||
previewContent.removeChild(iframe);
|
|
||||||
};
|
|
||||||
|
|
||||||
previewContent.addEventListener("MozPlayPlugin", playPluginHandler, true);
|
|
||||||
|
|
||||||
if (!playPreviewInfo.ignoreCTP) {
|
|
||||||
this._showClickToPlayNotification(plugin, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reshowClickToPlayNotification: function () {
|
|
||||||
let contentWindow = this.global.content;
|
|
||||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
|
||||||
let plugins = cwu.plugins;
|
|
||||||
for (let plugin of plugins) {
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
if (overlay)
|
|
||||||
overlay.removeEventListener("click", this, true);
|
|
||||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
|
||||||
if (this.canActivatePlugin(objLoadingContent))
|
|
||||||
this._handleClickToPlayEvent(plugin);
|
|
||||||
}
|
|
||||||
this._showClickToPlayNotification(null, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Match the behaviour of nsPermissionManager
|
|
||||||
_getHostFromPrincipal: function (principal) {
|
|
||||||
if (!principal.URI || principal.URI.schemeIs("moz-nullprincipal")) {
|
|
||||||
return "(null)";
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (principal.URI.host)
|
|
||||||
return principal.URI.host;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
return principal.origin;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Activate the plugins that the user has specified.
|
|
||||||
*/
|
|
||||||
activatePlugins: function (pluginInfo, newState) {
|
|
||||||
let contentWindow = this.global.content;
|
|
||||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
|
||||||
let plugins = cwu.plugins;
|
|
||||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
|
||||||
|
|
||||||
let pluginFound = false;
|
|
||||||
for (let plugin of plugins) {
|
|
||||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
|
||||||
if (!this.isKnownPlugin(plugin)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
|
|
||||||
pluginFound = true;
|
|
||||||
if (newState == "block") {
|
|
||||||
plugin.reload(true);
|
|
||||||
} else {
|
|
||||||
if (this.canActivatePlugin(plugin)) {
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
if (overlay) {
|
|
||||||
overlay.removeEventListener("click", this, true);
|
|
||||||
}
|
|
||||||
plugin.playPlugin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are no instances of the plugin on the page any more, what the
|
|
||||||
// user probably needs is for us to allow and then refresh.
|
|
||||||
if (newState != "block" && !pluginFound) {
|
|
||||||
this.reloadPage();
|
|
||||||
}
|
|
||||||
this.updateNotificationUI();
|
|
||||||
},
|
|
||||||
|
|
||||||
_showClickToPlayNotification: function (plugin, showNow) {
|
|
||||||
let plugins = [];
|
|
||||||
|
|
||||||
// If plugin is null, that means the user has navigated back to a page with
|
|
||||||
// plugins, and we need to collect all the plugins.
|
|
||||||
if (plugin === null) {
|
|
||||||
let contentWindow = this.global.content;
|
|
||||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
|
||||||
// cwu.plugins may contain non-plugin <object>s, filter them out
|
|
||||||
plugins = cwu.plugins.filter((plugin) =>
|
|
||||||
plugin.getContentTypeForMIMEType(plugin.actualType) == Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
|
||||||
|
|
||||||
if (plugins.length == 0) {
|
|
||||||
this.removeNotification("click-to-play-plugins");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
plugins = [plugin];
|
|
||||||
}
|
|
||||||
|
|
||||||
let pluginData = this.pluginData;
|
|
||||||
|
|
||||||
let principal = this.global.content.document.nodePrincipal;
|
|
||||||
let principalHost = this._getHostFromPrincipal(principal);
|
|
||||||
|
|
||||||
for (let p of plugins) {
|
|
||||||
let pluginInfo = this._getPluginInfo(p);
|
|
||||||
if (pluginInfo.permissionString === null) {
|
|
||||||
Cu.reportError("No permission string for active plugin.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pluginData.has(pluginInfo.permissionString)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let permissionObj = Services.perms.
|
|
||||||
getPermissionObject(principal, pluginInfo.permissionString, false);
|
|
||||||
if (permissionObj) {
|
|
||||||
pluginInfo.pluginPermissionHost = permissionObj.host;
|
|
||||||
pluginInfo.pluginPermissionType = permissionObj.expireType;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pluginInfo.pluginPermissionHost = principalHost;
|
|
||||||
pluginInfo.pluginPermissionType = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.pluginData.set(pluginInfo.permissionString, pluginInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.global.sendAsyncMessage("PluginContent:ShowClickToPlayNotification", {
|
|
||||||
plugins: [... this.pluginData.values()],
|
|
||||||
showNow: showNow,
|
|
||||||
host: principalHost,
|
|
||||||
}, null, principal);
|
|
||||||
},
|
|
||||||
|
|
||||||
updateNotificationUI: function () {
|
|
||||||
// Make a copy of the actions from the last popup notification.
|
|
||||||
let haveInsecure = false;
|
|
||||||
let actions = new Map();
|
|
||||||
for (let action of this.pluginData.values()) {
|
|
||||||
switch (action.fallbackType) {
|
|
||||||
// haveInsecure will trigger the red flashing icon and the infobar
|
|
||||||
// styling below
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
|
|
||||||
haveInsecure = true;
|
|
||||||
// fall through
|
|
||||||
|
|
||||||
case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
|
|
||||||
actions.set(action.permissionString, action);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove plugins that are already active, or large enough to show an overlay.
|
|
||||||
let contentWindow = this.global.content;
|
|
||||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
|
||||||
for (let plugin of cwu.plugins) {
|
|
||||||
let info = this._getPluginInfo(plugin);
|
|
||||||
if (!actions.has(info.permissionString)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let fallbackType = info.fallbackType;
|
|
||||||
if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
|
||||||
actions.delete(info.permissionString);
|
|
||||||
if (actions.size == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
|
|
||||||
fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE &&
|
|
||||||
fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
if (!overlay) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let shouldShow = this.shouldShowOverlay(plugin, overlay);
|
|
||||||
this.setVisibility(plugin, overlay, shouldShow);
|
|
||||||
if (shouldShow) {
|
|
||||||
actions.delete(info.permissionString);
|
|
||||||
if (actions.size == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are any items remaining in `actions` now, they are hidden
|
|
||||||
// plugins that need a notification bar.
|
|
||||||
let principal = contentWindow.document.nodePrincipal;
|
|
||||||
this.global.sendAsyncMessage("PluginContent:UpdateHiddenPluginUI", {
|
|
||||||
haveInsecure: haveInsecure,
|
|
||||||
actions: [... actions.values()],
|
|
||||||
host: this._getHostFromPrincipal(principal),
|
|
||||||
}, null, principal);
|
|
||||||
},
|
|
||||||
|
|
||||||
removeNotification: function (name) {
|
|
||||||
this.global.sendAsyncMessage("PluginContent:RemoveNotification", { name: name });
|
|
||||||
},
|
|
||||||
|
|
||||||
clearPluginDataCache: function () {
|
|
||||||
this.pluginData.clear();
|
|
||||||
},
|
|
||||||
|
|
||||||
hideNotificationBar: function (name) {
|
|
||||||
this.global.sendAsyncMessage("PluginContent:HideNotificationBar", { name: name });
|
|
||||||
},
|
|
||||||
|
|
||||||
// Crashed-plugin event listener. Called for every instance of a
|
|
||||||
// plugin in content.
|
|
||||||
pluginInstanceCrashed: function (target, aEvent) {
|
|
||||||
// Ensure the plugin and event are of the right type.
|
|
||||||
if (!(aEvent instanceof Ci.nsIDOMCustomEvent))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let propBag = aEvent.detail.QueryInterface(Ci.nsIPropertyBag2);
|
|
||||||
let submittedReport = propBag.getPropertyAsBool("submittedCrashReport");
|
|
||||||
let doPrompt = true; // XXX followup for .getPropertyAsBool("doPrompt");
|
|
||||||
let submitReports = true; // XXX followup for .getPropertyAsBool("submitReports");
|
|
||||||
let pluginName = propBag.getPropertyAsAString("pluginName");
|
|
||||||
let pluginDumpID = propBag.getPropertyAsAString("pluginDumpID");
|
|
||||||
let browserDumpID = null;
|
|
||||||
let gmpPlugin = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
browserDumpID = propBag.getPropertyAsAString("browserDumpID");
|
|
||||||
} catch (e) {
|
|
||||||
// For GMP crashes we don't get a browser dump.
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
gmpPlugin = propBag.getPropertyAsBool("gmpPlugin");
|
|
||||||
} catch (e) {
|
|
||||||
// This property is only set for GMP plugins.
|
|
||||||
}
|
|
||||||
|
|
||||||
// For non-GMP plugins, remap the plugin name to a more user-presentable form.
|
|
||||||
if (!gmpPlugin) {
|
|
||||||
pluginName = this.makeNicePluginName(pluginName);
|
|
||||||
}
|
|
||||||
|
|
||||||
let messageString = gNavigatorBundle.formatStringFromName("crashedpluginsMessage.title", [pluginName], 1);
|
|
||||||
|
|
||||||
let plugin = null, doc;
|
|
||||||
if (target instanceof Ci.nsIObjectLoadingContent) {
|
|
||||||
plugin = target;
|
|
||||||
doc = plugin.ownerDocument;
|
|
||||||
} else {
|
|
||||||
doc = target.document;
|
|
||||||
if (!doc) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// doPrompt is specific to the crashed plugin overlay, and
|
|
||||||
// therefore is not applicable for window-global plugins.
|
|
||||||
doPrompt = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let status;
|
|
||||||
#ifdef MOZ_CRASHREPORTER
|
|
||||||
// Determine which message to show regarding crash reports.
|
|
||||||
if (submittedReport) { // submitReports && !doPrompt, handled in observer
|
|
||||||
status = "submitted";
|
|
||||||
}
|
|
||||||
else if (!submitReports && !doPrompt) {
|
|
||||||
status = "noSubmit";
|
|
||||||
}
|
|
||||||
else if (!pluginDumpID) {
|
|
||||||
// If we don't have a minidumpID, we can't (or didn't) submit anything.
|
|
||||||
// This can happen if the plugin is killed from the task manager.
|
|
||||||
status = "noReport";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
status = "please";
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we don't have a minidumpID, we can't (or didn't) submit anything.
|
|
||||||
// This can happen if the plugin is killed from the task manager.
|
|
||||||
if (!pluginDumpID) {
|
|
||||||
status = "noReport";
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're showing the link to manually trigger report submission, we'll
|
|
||||||
// want to be able to update all the instances of the UI for this crash to
|
|
||||||
// show an updated message when a report is submitted.
|
|
||||||
if (doPrompt) {
|
|
||||||
let observer = {
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
|
||||||
Ci.nsISupportsWeakReference]),
|
|
||||||
observe : (subject, topic, data) => {
|
|
||||||
let propertyBag = subject;
|
|
||||||
if (!(propertyBag instanceof Ci.nsIPropertyBag2))
|
|
||||||
return;
|
|
||||||
// Ignore notifications for other crashes.
|
|
||||||
if (propertyBag.get("minidumpID") != pluginDumpID)
|
|
||||||
return;
|
|
||||||
let statusDiv = this.getPluginUI(plugin, "submitStatus");
|
|
||||||
statusDiv.setAttribute("status", data);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEvent : function(event) {
|
|
||||||
// Not expected to be called, just here for the closure.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use a weak reference, so we don't have to remove it...
|
|
||||||
Services.obs.addObserver(observer, "crash-report-status", true);
|
|
||||||
// ...alas, now we need something to hold a strong reference to prevent
|
|
||||||
// it from being GC. But I don't want to manually manage the reference's
|
|
||||||
// lifetime (which should be no greater than the page).
|
|
||||||
// Clever solution? Use a closue with an event listener on the document.
|
|
||||||
// When the doc goes away, so do the listener references and the closure.
|
|
||||||
doc.addEventListener("mozCleverClosureHack", observer, false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
let isShowing = false;
|
|
||||||
|
|
||||||
if (plugin) {
|
|
||||||
// If there's no plugin (an <object> or <embed> element), this call is
|
|
||||||
// for a window-global plugin. In this case, there's no overlay to show.
|
|
||||||
isShowing = _setUpPluginOverlay.call(this, plugin, doPrompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isShowing) {
|
|
||||||
// If a previous plugin on the page was too small and resulted in adding a
|
|
||||||
// notification bar, then remove it because this plugin instance it big
|
|
||||||
// enough to serve as in-content notification.
|
|
||||||
this.hideNotificationBar("plugin-crashed");
|
|
||||||
doc.mozNoPluginCrashedNotification = true;
|
|
||||||
} else {
|
|
||||||
// If another plugin on the page was large enough to show our UI, we don't
|
|
||||||
// want to show a notification bar.
|
|
||||||
if (!doc.mozNoPluginCrashedNotification) {
|
|
||||||
this.global.sendAsyncMessage("PluginContent:ShowPluginCrashedNotification", {
|
|
||||||
messageString: messageString,
|
|
||||||
pluginDumpID: pluginDumpID,
|
|
||||||
browserDumpID: browserDumpID,
|
|
||||||
});
|
|
||||||
// Remove the notification when the page is reloaded.
|
|
||||||
doc.defaultView.top.addEventListener("unload", event => {
|
|
||||||
this.hideNotificationBar("plugin-crashed");
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the crashed-plugin placeholder.
|
|
||||||
// Returns true if the plugin overlay is visible.
|
|
||||||
function _setUpPluginOverlay(plugin, doPromptSubmit) {
|
|
||||||
if (!plugin) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force a layout flush so the binding is attached.
|
|
||||||
plugin.clientTop;
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
|
||||||
let statusDiv = this.getPluginUI(plugin, "submitStatus");
|
|
||||||
|
|
||||||
if (doPromptSubmit) {
|
|
||||||
this.getPluginUI(plugin, "submitButton").addEventListener("click",
|
|
||||||
function (event) {
|
|
||||||
if (event.button != 0 || !event.isTrusted)
|
|
||||||
return;
|
|
||||||
this.submitReport(pluginDumpID, browserDumpID, plugin);
|
|
||||||
pref.setBoolPref("", optInCB.checked);
|
|
||||||
}.bind(this));
|
|
||||||
let optInCB = this.getPluginUI(plugin, "submitURLOptIn");
|
|
||||||
let pref = Services.prefs.getBranch("dom.ipc.plugins.reportCrashURL");
|
|
||||||
optInCB.checked = pref.getBoolPref("");
|
|
||||||
}
|
|
||||||
|
|
||||||
statusDiv.setAttribute("status", status);
|
|
||||||
|
|
||||||
let helpIcon = this.getPluginUI(plugin, "helpIcon");
|
|
||||||
this.addLinkClickCallback(helpIcon, "openHelpPage");
|
|
||||||
|
|
||||||
let crashText = this.getPluginUI(plugin, "crashedText");
|
|
||||||
crashText.textContent = messageString;
|
|
||||||
|
|
||||||
let link = this.getPluginUI(plugin, "reloadLink");
|
|
||||||
this.addLinkClickCallback(link, "reloadPage");
|
|
||||||
|
|
||||||
let isShowing = this.shouldShowOverlay(plugin, overlay);
|
|
||||||
|
|
||||||
// Is the <object>'s size too small to hold what we want to show?
|
|
||||||
if (!isShowing) {
|
|
||||||
// First try hiding the crash report submission UI.
|
|
||||||
statusDiv.removeAttribute("status");
|
|
||||||
|
|
||||||
isShowing = this.shouldShowOverlay(plugin, overlay);
|
|
||||||
}
|
|
||||||
this.setVisibility(plugin, overlay, isShowing);
|
|
||||||
|
|
||||||
return isShowing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -44,7 +44,6 @@ if CONFIG['NIGHTLY_BUILD']:
|
|||||||
|
|
||||||
EXTRA_PP_JS_MODULES += [
|
EXTRA_PP_JS_MODULES += [
|
||||||
'AboutHome.jsm',
|
'AboutHome.jsm',
|
||||||
'PluginContent.jsm',
|
|
||||||
'RecentWindow.jsm',
|
'RecentWindow.jsm',
|
||||||
'UITour.jsm',
|
'UITour.jsm',
|
||||||
'webrtcUI.jsm',
|
'webrtcUI.jsm',
|
||||||
|
@ -75,21 +75,19 @@ function part3(aTestPlugin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function part4() {
|
function part4() {
|
||||||
let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser);
|
ok(PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser), "part4: should have a click-to-play notification");
|
||||||
waitForCondition(condition, () => {
|
gPluginBrowser.removeEventListener("PluginBindingAttached", part4);
|
||||||
gPluginBrowser.removeEventListener("PluginBindingAttached", part4);
|
gBrowser.removeCurrentTab();
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
|
|
||||||
let pluginEl = get_addon_element(gManagerWindow, gTestPluginId);
|
let pluginEl = get_addon_element(gManagerWindow, gTestPluginId);
|
||||||
let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist");
|
let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist");
|
||||||
let alwaysActivateItem = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "always-activate-menuitem");
|
let alwaysActivateItem = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "always-activate-menuitem");
|
||||||
menu.selectedItem = alwaysActivateItem;
|
menu.selectedItem = alwaysActivateItem;
|
||||||
alwaysActivateItem.doCommand();
|
alwaysActivateItem.doCommand();
|
||||||
gBrowser.selectedTab = gBrowser.addTab();
|
gBrowser.selectedTab = gBrowser.addTab();
|
||||||
gPluginBrowser = gBrowser.selectedBrowser;
|
gPluginBrowser = gBrowser.selectedBrowser;
|
||||||
gPluginBrowser.addEventListener("load", part5, true);
|
gPluginBrowser.addEventListener("load", part5, true);
|
||||||
gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html";
|
gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html";
|
||||||
}, "part4: should have a click-to-play notification");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function part5() {
|
function part5() {
|
||||||
@ -120,22 +118,20 @@ function part6() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function part7() {
|
function part7() {
|
||||||
let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser);
|
ok(PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser), "part7: disabled plugins still show a notification");
|
||||||
waitForCondition(condition, () => {
|
let testPlugin = gPluginBrowser.contentDocument.getElementById("test");
|
||||||
let testPlugin = gPluginBrowser.contentDocument.getElementById("test");
|
ok(testPlugin, "part7: should have a plugin element in the page");
|
||||||
ok(testPlugin, "part7: should have a plugin element in the page");
|
let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||||
let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
ok(!objLoadingContent.activated, "part7: plugin should not be activated");
|
||||||
ok(!objLoadingContent.activated, "part7: plugin should not be activated");
|
|
||||||
|
|
||||||
gPluginBrowser.removeEventListener("PluginBindingAttached", part7);
|
gPluginBrowser.removeEventListener("PluginBindingAttached", part7);
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
|
|
||||||
let pluginEl = get_addon_element(gManagerWindow, gTestPluginId);
|
let pluginEl = get_addon_element(gManagerWindow, gTestPluginId);
|
||||||
let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
|
let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
|
||||||
is_element_visible(details, "part7: details link should be visible");
|
is_element_visible(details, "part7: details link should be visible");
|
||||||
EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow);
|
EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow);
|
||||||
wait_for_view_load(gManagerWindow, part8);
|
wait_for_view_load(gManagerWindow, part8);
|
||||||
}, "part7: disabled plugins still show a notification");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function part8() {
|
function part8() {
|
||||||
@ -184,21 +180,19 @@ function part10() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function part11() {
|
function part11() {
|
||||||
let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser);
|
ok(PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser), "part11: should have a click-to-play notification");
|
||||||
waitForCondition(condition, () => {
|
gPluginBrowser.removeEventListener("PluginBindingAttached", part11);
|
||||||
gPluginBrowser.removeEventListener("PluginBindingAttached", part11);
|
gBrowser.removeCurrentTab();
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
|
|
||||||
let pluginTag = getTestPluginTag();
|
let pluginTag = getTestPluginTag();
|
||||||
|
|
||||||
// causes appDisabled to be set
|
// causes appDisabled to be set
|
||||||
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml",
|
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml",
|
||||||
function() {
|
function() {
|
||||||
close_manager(gManagerWindow, function() {
|
close_manager(gManagerWindow, function() {
|
||||||
open_manager("addons://list/plugin", part12);
|
open_manager("addons://list/plugin", part12);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}, "part11: should have a click-to-play notification");
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function part12(aWindow) {
|
function part12(aWindow) {
|
||||||
|
Loading…
Reference in New Issue
Block a user