bug 1335697 Display permissions and post-install notifications from about:addons search
MozReview-Commit-ID: IqBoudbO7Vd
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -79,16 +79,17 @@ support-files =
browser_webext_nopermissions.xpi
browser_webext_update1.xpi
browser_webext_update2.xpi
browser_webext_update_icon1.xpi
browser_webext_update_icon2.xpi
browser_webext_update_perms1.xpi
browser_webext_update_perms2.xpi
browser_webext_update.json
+ browser_webext_search.xml
!/image/test/mochitest/blue.png
!/toolkit/content/tests/browser/common/mockTransfer.js
!/toolkit/modules/tests/browser/metadata_*.html
!/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi
!/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi
!/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi
!/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html
!/toolkit/mozapps/extensions/test/xpinstall/redirect.sjs
--- a/browser/base/content/test/general/browser_extension_permissions.js
+++ b/browser/base/content/test/general/browser_extension_permissions.js
@@ -1,31 +1,41 @@
"use strict";
+// See but 1340586 for proposal to reorganize permissions tests to
+// get rid of this...
+requestLongerTimeout(2);
+
const BASE = getRootDirectory(gTestPath)
.replace("chrome://mochitests/content/", "https://example.com/");
const INSTALL_PAGE = `${BASE}/file_install_extensions.html`;
const PERMS_XPI = "browser_webext_permissions.xpi";
const NO_PERMS_XPI = "browser_webext_nopermissions.xpi";
const ID = "permissions@test.mozilla.org";
-const DEFAULT_EXTENSION_ICON = "chrome://browser/content/extension.svg";
-
Services.perms.add(makeURI("https://example.com/"), "install",
Services.perms.ALLOW_ACTION);
registerCleanupFunction(async function() {
let addon = await AddonManager.getAddonByID(ID);
if (addon) {
ok(false, `Addon ${ID} was still installed at the end of the test`);
addon.uninstall();
}
});
+function isDefaultIcon(icon) {
+ // These are basically the same icon, but code within webextensions
+ // generates references to the former and generic add-ons manager code
+ // generates referces to the latter.
+ return (icon == "chrome://browser/content/extension.svg" ||
+ icon == "chrome://mozapps/skin/extensions/extensionGeneric.svg");
+}
+
function promisePopupNotificationShown(name) {
return new Promise(resolve => {
function popupshown() {
let notification = PopupNotifications.getNotification(name);
if (!notification) { return; }
ok(notification, `${name} notification shown`);
ok(PopupNotifications.isPanelOpen, "notification panel open");
@@ -51,17 +61,17 @@ function checkNotification(panel, filena
ok(icon.startsWith("jar:file://"), "Icon is a jar url");
ok(icon.endsWith("/icon.png"), "Icon is icon.png inside a jar");
is(header.getAttribute("hidden"), "", "Permission list header is visible");
is(ul.childElementCount, 4, "Permissions list has 4 entries");
// Real checking of the contents here is deferred until bug 1316996 lands
} else if (filename == NO_PERMS_XPI) {
// This extension has no icon, it should have the default
- is(icon, DEFAULT_EXTENSION_ICON, "Icon is the default extension icon");
+ ok(isDefaultIcon(icon), "Icon is the default extension icon");
is(header.getAttribute("hidden"), "true", "Permission list header is hidden");
is(ul.childElementCount, 0, "Permissions list has 0 entries");
}
}
// Navigate the current tab to the given url and return a Promise
// that resolves when the page is loaded.
@@ -101,16 +111,55 @@ const INSTALL_FUNCTIONS = [
await BrowserOpenAddonsMgr("addons://list/extension");
let contentWin = gBrowser.selectedTab.linkedBrowser.contentWindow;
// Do the install...
contentWin.gViewController.doCommand("cmd_installFromFile");
MockFilePicker.cleanup();
},
+
+ async function installSearch(filename) {
+ await SpecialPowers.pushPrefEnv({set: [
+ ["extensions.getAddons.maxResults", 10],
+ ["extensions.getAddons.search.url", `${BASE}/browser_webext_search.xml`],
+ ]});
+
+ let win = await BrowserOpenAddonsMgr("addons://list/extension");
+
+ let searchResultsPromise = new Promise(resolve => {
+ win.document.addEventListener("ViewChanged", resolve, {once: true});
+ });
+ let search = win.document.getElementById("header-search");
+ search.focus();
+ search.value = "search text";
+ EventUtils.synthesizeKey("VK_RETURN", {}, win);
+
+ await searchResultsPromise;
+ ok(win.gViewController.currentViewId.startsWith("addons://search"),
+ "about:addons is displaying search results");
+
+ let list = win.document.getElementById("search-list");
+ let item = null;
+ for (let child of list.childNodes) {
+ if (child.nodeName == "richlistitem" &&
+ child.mAddon.install.sourceURI.path.endsWith(filename)) {
+ item = child;
+ break;
+ }
+ }
+ ok(item, `Found ${filename} in search results`);
+
+ // abracadabara XBL
+ item.clientTop;
+
+ let install = win.document.getAnonymousElementByAttribute(item, "anonid", "install-status");
+ let button = win.document.getAnonymousElementByAttribute(install, "anonid", "install-remote-btn");
+ EventUtils.synthesizeMouseAtCenter(button, {}, win);
+ },
];
add_task(function* () {
yield SpecialPowers.pushPrefEnv({set: [
["extensions.webapi.testing", true],
["extensions.install.requireBuiltInCerts", false],
// XXX remove this when prompts are enabled by default
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_webext_search.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<searchresults total_results="2">
+ <addon>
+ <name>permissions test</name>
+ <type id='1'>Extension</type>
+ <guid>permissions@tests.mozilla.org</guid>
+ <version>1.1</version>
+ <authors>
+ <author>
+ <name>Test Creator</name>
+ <link>http://example.com/creator.html</link>
+ </author>
+ </authors>
+ <status id='4'>Public</status>
+ <compatible_applications>
+ <application>
+ <name>Firefox</name>
+ <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
+ <min_version>0</min_version>
+ <max_version>*</max_version>
+ </application>
+ </compatible_applications>
+ <compatible_os>ALL</compatible_os>
+ <install size="1">https://example.com/browser/browser/base/content/test/general/browser_webext_permissions.xpi</install>
+ </addon>
+
+ <addon>
+ <name>no permissions</name>
+ <type id='1'>Extension</type>
+ <guid>nopermissions@tests.mozilla.org</guid>
+ <version>1.0</version>
+ <authors>
+ <author>
+ <name>Test Creator</name>
+ <link>http://example.com/creator.html</link>
+ </author>
+ </authors>
+ <status id='4'>Public</status>
+ <compatible_applications>
+ <application>
+ <name>Firefox</name>
+ <appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
+ <min_version>0</min_version>
+ <max_version>*</max_version>
+ </application>
+ </compatible_applications>
+ <compatible_os>ALL</compatible_os>
+ <install size="1">https://example.com/browser/browser/base/content/test/general/browser_webext_nopermissions.xpi</install>
+ </addon>
+</searchresults>
+
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -2710,16 +2710,37 @@ var gSearchView = {
onDownloadCancelled(aInstall) {
this.removeInstall(aInstall);
},
onInstallCancelled(aInstall) {
this.removeInstall(aInstall);
},
+ onInstallEnded(aInstall) {
+ // If this is a webextension that was installed from this page,
+ // display the post-install notification.
+ if (!WEBEXT_PERMISSION_PROMPTS || !aInstall.addon.isWebExtension) {
+ return;
+ }
+
+ for (let item of this._listBox.childNodes) {
+ if (item.mInstall == aInstall) {
+ let subject = {
+ wrappedJSObject: {
+ target: getBrowserElement(),
+ addon: aInstall.addon,
+ },
+ };
+ Services.obs.notifyObservers(subject, "webextension-install-notify", null);
+ return;
+ }
+ }
+ },
+
removeInstall(aInstall) {
for (let item of this._listBox.childNodes) {
if (item.mInstall == aInstall) {
this._listBox.removeChild(item);
return;
}
}
},
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -648,16 +648,37 @@
"chrome,dialog,modal,centerscreen,resizable=no", data);
if (!data.accepted)
return;
}
delete this.mControl.mAddon;
this.mControl.mInstall = this.mInstall;
this.mControl.setAttribute("status", "installing");
+ let prompt = false;
+ try {
+ prompt = Services.prefs.getBoolPref("extensions.webextPermissionPrompts");
+ } catch (err) {}
+ if (prompt) {
+ this.mInstall.promptHandler = info => new Promise((resolve, reject) => {
+ let subject = {
+ wrappedJSObject: {
+ target: window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDocShell).chromeEventHandler,
+ info: {
+ addon: info.addon,
+ icon: info.addon.iconURL,
+ resolve,
+ reject,
+ },
+ },
+ };
+ Services.obs.notifyObservers(subject, "webextension-permission-prompt", null);
+ });
+ }
this.mInstall.install();
]]></body>
</method>
<method name="undoAction">
<body><![CDATA[
if (!this.mAddon)
return;