Bug 1342896 Don't show prompts for interactive webextension updates with no new permissions draft
authorAndrew Swan <aswan@mozilla.com>
Fri, 03 Mar 2017 11:05:35 -0800
changeset 493465 5bc01b088bf554a8a94897979a1918206dad4654
parent 493227 77d5a39a4677ed8e32a7ed46561c962d807fa7b1
child 547868 de0b4f4144f4a09f3132a4b39c1e238a37016c65
push id47769
push useraswan@mozilla.com
push dateSat, 04 Mar 2017 03:34:54 +0000
bugs1342896
milestone54.0a1
Bug 1342896 Don't show prompts for interactive webextension updates with no new permissions MozReview-Commit-ID: 50SP3eL79Qm
browser/base/content/test/webextensions/browser.ini
browser/base/content/test/webextensions/browser_extension_update_interactive.js
browser/base/content/test/webextensions/browser_update_interactive.js
browser/base/content/test/webextensions/browser_update_interactive_noprompt.js
browser/modules/ExtensionsUI.jsm
--- a/browser/base/content/test/webextensions/browser.ini
+++ b/browser/base/content/test/webextensions/browser.ini
@@ -12,13 +12,14 @@ support-files =
   browser_webext_update_icon2.xpi
   browser_webext_update_perms1.xpi
   browser_webext_update_perms2.xpi
   browser_webext_update.json
   browser_webext_search.xml
 
 [browser_extension_sideloading.js]
 [browser_extension_update_background.js]
-[browser_extension_update_interactive.js]
 [browser_permissions_addons_search.js]
 [browser_permissions_installTrigger.js]
 [browser_permissions_local_file.js]
 [browser_permissions_mozAddonManager.js]
+[browser_update_interactive.js]
+[browser_update_interactive_noprompt.js]
rename from browser/base/content/test/webextensions/browser_extension_update_interactive.js
rename to browser/base/content/test/webextensions/browser_update_interactive.js
--- a/browser/base/content/test/webextensions/browser_extension_update_interactive.js
+++ b/browser/base/content/test/webextensions/browser_update_interactive.js
@@ -1,12 +1,11 @@
 const {AddonManagerPrivate} = Cu.import("resource://gre/modules/AddonManager.jsm", {});
 
 const ID = "update2@tests.mozilla.org";
-const ID_LEGACY = "legacy_update@tests.mozilla.org";
 
 // Set some prefs that apply to all the tests in this file
 add_task(function* setup() {
   yield SpecialPowers.pushPrefEnv({set: [
     // We don't have pre-pinned certificates for the local mochitest server
     ["extensions.install.requireBuiltInCerts", false],
     ["extensions.update.requireBuiltInCerts", false],
 
@@ -129,48 +128,8 @@ add_task(() => interactiveUpdateTest(fal
 // Invoke an invidual extension's "Find Updates" menu item
 function checkOne(win, addon) {
   win.gViewController.doCommand("cmd_findItemUpdates", addon);
 }
 
 // Test "Find Updates" with both auto-update settings
 add_task(() => interactiveUpdateTest(true, checkOne));
 add_task(() => interactiveUpdateTest(false, checkOne));
-
-// Check that an update from a legacy extension to a webextensino
-// does not display a prompt
-add_task(async function() {
-  await SpecialPowers.pushPrefEnv({set: [
-    // Point updates to the local mochitest server
-    ["extensions.update.url", `${BASE}/browser_webext_update.json`],
-  ]});
-
-  // Navigate away to ensure that BrowserOpenAddonMgr() opens a new tab
-  gBrowser.selectedBrowser.loadURI("about:robots");
-  await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
-
-  // Install initial version of the test extension
-  let addon = await promiseInstallAddon(`${BASE}/browser_legacy.xpi`);
-  ok(addon, "Addon was installed");
-  is(addon.version, "1.1", "Version 1 of the addon is installed");
-
-  // Go to Extensions in about:addons
-  let win = await BrowserOpenAddonsMgr("addons://list/extension");
-
-  let sawPopup = false;
-  PopupNotifications.panel.addEventListener("popupshown",
-                                            () => sawPopup = true,
-                                            {once: true});
-
-  // Trigger an update check, we should see the update get applied
-  let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
-  win.gViewController.doCommand("cmd_findAllUpdates");
-  await updatePromise;
-
-  addon = await AddonManager.getAddonByID(ID_LEGACY);
-  is(addon.version, "2.0", "Should have upgraded");
-
-  ok(!sawPopup, "Should not have seen a permission notification");
-
-  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
-  addon.uninstall();
-  await SpecialPowers.popPrefEnv();
-});
copy from browser/base/content/test/webextensions/browser_extension_update_interactive.js
copy to browser/base/content/test/webextensions/browser_update_interactive_noprompt.js
--- a/browser/base/content/test/webextensions/browser_extension_update_interactive.js
+++ b/browser/base/content/test/webextensions/browser_update_interactive_noprompt.js
@@ -1,176 +1,62 @@
-const {AddonManagerPrivate} = Cu.import("resource://gre/modules/AddonManager.jsm", {});
-
-const ID = "update2@tests.mozilla.org";
-const ID_LEGACY = "legacy_update@tests.mozilla.org";
 
 // Set some prefs that apply to all the tests in this file
 add_task(function* setup() {
   yield SpecialPowers.pushPrefEnv({set: [
     // We don't have pre-pinned certificates for the local mochitest server
     ["extensions.install.requireBuiltInCerts", false],
     ["extensions.update.requireBuiltInCerts", false],
 
+    // Point updates to the local mochitest server
+    ["extensions.update.url", `${BASE}/browser_webext_update.json`],
+
     // XXX remove this when prompts are enabled by default
     ["extensions.webextPermissionPrompts", true],
   ]});
 });
 
-// Helper function to test a specific scenario for interactive updates.
-// `checkFn` is a callable that triggers a check for updates.
-// `autoUpdate` specifies whether the test should be run with
-// updates applied automatically or not.
-function* interactiveUpdateTest(autoUpdate, checkFn) {
-  yield SpecialPowers.pushPrefEnv({set: [
-    ["extensions.update.autoUpdateDefault", autoUpdate],
-
-    // Point updates to the local mochitest server
-    ["extensions.update.url", `${BASE}/browser_webext_update.json`],
-  ]});
-
-  // Trigger an update check, manually applying the update if we're testing
-  // without auto-update.
-  async function triggerUpdate(win, addon) {
-    let manualUpdatePromise;
-    if (!autoUpdate) {
-      manualUpdatePromise = new Promise(resolve => {
-        let listener = {
-          onNewInstall() {
-            AddonManager.removeInstallListener(listener);
-            resolve();
-          },
-        };
-        AddonManager.addInstallListener(listener);
-      });
-    }
-
-    let promise = checkFn(win, addon);
-
-    if (manualUpdatePromise) {
-      await manualUpdatePromise;
-
-      let list = win.document.getElementById("addon-list");
-
-      // Make sure we have XBL bindings
-      list.clientHeight;
-
-      let item = list.children.find(_item => _item.value == ID);
-      EventUtils.synthesizeMouseAtCenter(item._updateBtn, {}, win);
-    }
-
-    return {promise};
-  }
-
-  // Navigate away from the starting page to force about:addons to load
-  // in a new tab during the tests below.
-  gBrowser.selectedBrowser.loadURI("about:robots");
-  yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
-
-  // Install version 1.0 of the test extension
-  let addon = yield promiseInstallAddon(`${BASE}/browser_webext_update1.xpi`);
-  ok(addon, "Addon was installed");
-  is(addon.version, "1.0", "Version 1 of the addon is installed");
-
-  let win = yield BrowserOpenAddonsMgr("addons://list/extension");
-
-  // Trigger an update check
-  let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
-  let {promise: checkPromise} = yield triggerUpdate(win, addon);
-  let panel = yield popupPromise;
-
-  // Click the cancel button, wait to see the cancel event
-  let cancelPromise = promiseInstallEvent(addon, "onInstallCancelled");
-  panel.secondaryButton.click();
-  yield cancelPromise;
-
-  addon = yield AddonManager.getAddonByID(ID);
-  is(addon.version, "1.0", "Should still be running the old version");
-
-  // Make sure the update check is completely finished.
-  yield checkPromise;
-
-  // Trigger a new update check
-  popupPromise = promisePopupNotificationShown("addon-webext-permissions");
-  checkPromise = (yield triggerUpdate(win, addon)).promise;
-
-  // This time, accept the upgrade
-  let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
-  panel = yield popupPromise;
-  panel.button.click();
-
-  addon = yield updatePromise;
-  is(addon.version, "2.0", "Should have upgraded");
-
-  yield checkPromise;
-
-  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
-  addon.uninstall();
-  yield SpecialPowers.popPrefEnv();
-}
-
-// Invoke the "Check for Updates" menu item
-function checkAll(win) {
-  win.gViewController.doCommand("cmd_findAllUpdates");
-  return new Promise(resolve => {
-    let observer = {
-      observe(subject, topic, data) {
-        Services.obs.removeObserver(observer, "EM-update-check-finished");
-        resolve();
-      },
-    };
-    Services.obs.addObserver(observer, "EM-update-check-finished", false);
-  });
-}
-
-// Test "Check for Updates" with both auto-update settings
-add_task(() => interactiveUpdateTest(true, checkAll));
-add_task(() => interactiveUpdateTest(false, checkAll));
-
-
-// Invoke an invidual extension's "Find Updates" menu item
-function checkOne(win, addon) {
-  win.gViewController.doCommand("cmd_findItemUpdates", addon);
-}
-
-// Test "Find Updates" with both auto-update settings
-add_task(() => interactiveUpdateTest(true, checkOne));
-add_task(() => interactiveUpdateTest(false, checkOne));
-
-// Check that an update from a legacy extension to a webextensino
-// does not display a prompt
-add_task(async function() {
-  await SpecialPowers.pushPrefEnv({set: [
-    // Point updates to the local mochitest server
-    ["extensions.update.url", `${BASE}/browser_webext_update.json`],
-  ]});
-
+// Helper to test that an update of a given extension does not
+// generate any permission prompts.
+async function testUpdateNoPrompt(filename, id,
+                                  initialVersion = "1.0", updateVersion = "2.0") {
   // Navigate away to ensure that BrowserOpenAddonMgr() opens a new tab
   gBrowser.selectedBrowser.loadURI("about:robots");
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 
   // Install initial version of the test extension
-  let addon = await promiseInstallAddon(`${BASE}/browser_legacy.xpi`);
+  let addon = await promiseInstallAddon(`${BASE}/${filename}`);
   ok(addon, "Addon was installed");
-  is(addon.version, "1.1", "Version 1 of the addon is installed");
+  is(addon.version, initialVersion, "Version 1 of the addon is installed");
 
   // Go to Extensions in about:addons
   let win = await BrowserOpenAddonsMgr("addons://list/extension");
 
   let sawPopup = false;
-  PopupNotifications.panel.addEventListener("popupshown",
-                                            () => sawPopup = true,
-                                            {once: true});
+  function popupListener() {
+    sawPopup = true;
+  }
+  PopupNotifications.panel.addEventListener("popupshown", popupListener);
 
   // Trigger an update check, we should see the update get applied
   let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
   win.gViewController.doCommand("cmd_findAllUpdates");
   await updatePromise;
 
-  addon = await AddonManager.getAddonByID(ID_LEGACY);
-  is(addon.version, "2.0", "Should have upgraded");
+  addon = await AddonManager.getAddonByID(id);
+  is(addon.version, updateVersion, "Should have upgraded");
 
   ok(!sawPopup, "Should not have seen a permission notification");
+  PopupNotifications.panel.removeEventListener("popupshown", popupListener);
 
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
   addon.uninstall();
-  await SpecialPowers.popPrefEnv();
-});
+}
+
+// Test that we don't see a prompt when updating from a legacy
+// extension to a webextension.
+add_task(() => testUpdateNoPrompt("browser_legacy.xpi",
+                                  "legacy_update@tests.mozilla.org", "1.1"));
+
+// Test that we don't see a prompt when no new promptable permissions
+// are added.
+add_task(() => testUpdateNoPrompt("browser_webext_update_perms1.xpi",
+                                  "update_perms@tests.mozilla.org"));
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -136,16 +136,22 @@ this.ExtensionsUI = {
       // there are multiple simultaneous installs happening, see
       // bug 1329884 for a longer explanation.
       let progressNotification = target.ownerGlobal.PopupNotifications.getNotification("addon-progress", target);
       if (progressNotification) {
         progressNotification.remove();
       }
 
       let strings = this._buildStrings(info);
+      // If this is an update with no promptable permissions, just apply it
+      if (info.type == "update" && strings.msgs.length == 0) {
+        info.resolve();
+        return;
+      }
+
       this.showPermissionsPrompt(target, strings, info.icon).then(answer => {
         if (answer) {
           info.resolve();
         } else {
           info.reject();
         }
       });
     } else if (topic == "webextension-update-permissions") {