bug 1335697 Display permissions and post-install notifications from about:addons search r=mossop
authorAndrew Swan <aswan@mozilla.com>
Tue, 07 Feb 2017 20:22:26 -0800
changeset 343560 b49222f9716959da6f21bf02acfe2d39752458c2
parent 343559 16b0fffa128302377ac425c51bcd4d5d5a1d9725
child 343561 0b13fb9ee2def4fca2f9676bb0b3683b8581a9ac
push id31381
push userkwierso@gmail.com
push dateFri, 17 Feb 2017 20:45:51 +0000
treeherdermozilla-central@f302def88fe5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmossop
bugs1335697
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1335697 Display permissions and post-install notifications from about:addons search r=mossop MozReview-Commit-ID: IqBoudbO7Vd
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_extension_permissions.js
browser/base/content/test/general/browser_webext_search.xml
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/content/extensions.xml
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -81,16 +81,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
@@ -2715,16 +2715,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;