[Pkg-mozext-commits] [requestpolicy] 61/80: show a notice when multiple RP versions are active

David Prévot taffit at moszumanska.debian.org
Sun Jul 5 15:02:31 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository requestpolicy.

commit 9c82f30131a5205307424874aaddb6d49fada7c0
Author: Martin Kimmerle <dev at 256k.de>
Date:   Tue Jun 23 03:09:03 2015 +0200

    show a notice when multiple RP versions are active
    
    When RP is installed/enabled, it will check if there are other
    versions of RP installed and enabled. RP will also observe addon
    install/enable actions, so that it recognizes when another RP
    version gets active.
    
    In any of the above cases, a new tab will be opened, which will
    show a notice that there shouldn't be multiple instances of RP
    active at the same time.
    
    A Marionette test suite ensures the desired functionality.
    Thanks to the "addons" library, this can be accomplished quite
    easily.
---
 Makefile                                           |   8 +-
 src/content/main/requestpolicy-service.jsm         | 114 +++++++++++++-
 src/content/multiple-installations.html            |  78 ++++++++++
 tests/marionette/tests/manifest.ini                |   1 +
 .../tests/test_multiple_installations.py           | 167 +++++++++++++++++++++
 5 files changed, 366 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index a624268..36b93fd 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,7 @@ source_files := $(shell find $(source_dirname) -type f -regex ".*\.jsm?") \
 		$(source_dirname)/README \
 		$(wildcard $(source_dirname)/content/settings/*.css) \
 		$(wildcard $(source_dirname)/content/settings/*.html) \
+		$(wildcard $(source_dirname)/content/*.html) \
 		$(wildcard $(source_dirname)/content/ui/*.xul) \
 		$(wildcard $(source_dirname)/locale/*/*.dtd) \
 		$(wildcard $(source_dirname)/locale/*/*.properties) \
@@ -536,7 +537,12 @@ marionette_tests += tests/marionette/tests/manifest.ini
 
 
 .PHONY: marionette
-marionette: venv $(unit_testing__xpi_file) $(dev_helper__xpi_file) $(dummy_ext__xpi_file)
+marionette: venv \
+		unit-testing-xpi \
+		dev-helper-xpi \
+		dummy-xpi \
+		specific-xpi \
+		amo-xpi
 	@# Due to Mozilla Bug 1173502, the profile needs to be created and
 	@# removed directly.
 	( \
diff --git a/src/content/main/requestpolicy-service.jsm b/src/content/main/requestpolicy-service.jsm
index 22e5942..db03329 100644
--- a/src/content/main/requestpolicy-service.jsm
+++ b/src/content/main/requestpolicy-service.jsm
@@ -29,6 +29,7 @@ let EXPORTED_SYMBOLS = ["rpService"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/AddonManager.jsm");
 
 Cu.import("chrome://rpcontinued/content/lib/script-loader.jsm");
 ScriptLoader.importModules([
@@ -118,6 +119,115 @@ let rpService = (function() {
   }
 
 
+  /**
+   * Module for detecting installations of other RequestPolicy versions,
+   * which have a different extension ID.
+   */
+  var DetectorForOtherInstallations = (function () {
+    const NOTICE_URL = "chrome://rpcontinued/content/" +
+        "multiple-installations.html";
+
+    // The other extension IDs of RequestPolicy.
+    var addonIDs = Object.freeze([
+      "requestpolicy at requestpolicy.com",
+      // #ifdef AMO
+      // In the AMO version the non-AMO version needs to be detected.
+      "rpcontinued at non-amo.requestpolicy.org",
+      // #else
+      // In the non-AMO version the AMO version needs to be detected.
+      "rpcontinued at requestpolicy.org",
+      // #endif
+    ]);
+
+    var addonListener = {
+      onEnabled: checkAddon,
+      onInstalled: checkAddon
+    };
+
+    function checkAddon(addon) {
+      for (let id of addonIDs) {
+        if (addon.id === id) {
+          openTab();
+          return;
+        }
+      }
+    }
+
+    ProcessEnvironment.addStartupFunction(Environment.LEVELS.UI, function () {
+      AddonManager.addAddonListener(addonListener);
+    });
+
+    ProcessEnvironment.addShutdownFunction(Environment.LEVELS.UI, function () {
+      AddonManager.removeAddonListener(addonListener);
+    });
+
+    /**
+     * Open the tab with the 'multiple installations' notice.
+     *
+     * @return {Boolean} whether opening the tab was successful
+     */
+    function openTab() {
+      var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
+          .getService(Ci.nsIWindowMediator);
+      var mostRecentWindow = wm.getMostRecentWindow("navigator:browser");
+
+      // the gBrowser object of the firefox window
+      var _gBrowser = mostRecentWindow.getBrowser();
+
+      if (typeof(_gBrowser.addTab) !== "function") {
+        return false;
+      }
+
+      _gBrowser.selectedTab = _gBrowser.addTab(NOTICE_URL);
+
+      return true;
+    }
+
+    function isAddonActive(addon) {
+      if (addon === null) {
+        return false;
+      }
+
+      return addon.isActive;
+    }
+
+    // On startup, the tab should be opened only once.
+    var initialCheckDone = false;
+
+    function addonListCallback(addons) {
+      var activeAddons = addons.filter(isAddonActive);
+      if (activeAddons.length === 0) {
+        // no other RequestPolicy version is active
+        return;
+      }
+
+      if (initialCheckDone === true) {
+        return;
+      }
+
+      var rv = openTab();
+
+      if (rv === true) {
+        initialCheckDone = true;
+      }
+    }
+
+    /**
+     * Check if other RequestPolicy versions (with other extension IDs)
+     * are installed. If so, a tab with a notice will be opened.
+     */
+    function checkForOtherInstallations() {
+      if (initialCheckDone === true) {
+        return;
+      }
+
+      AddonManager.getAddonsByIDs(addonIDs, addonListCallback);
+    }
+
+    return {checkForOtherInstallations: checkForOtherInstallations};
+  })();
+
+
 
 
 
@@ -149,9 +259,10 @@ let rpService = (function() {
       Environment.LEVELS.UI,
       function(data, reason) {
         if (reason !== C.APP_STARTUP) {
-          // In case of the app's startup `showWelcomeWindow()` will be
+          // In case of the app's startup, the following functions will be
           // called when "sessionstore-windows-restored" is observed.
           showWelcomeWindow();
+          DetectorForOtherInstallations.checkForOtherInstallations();
         }
       });
 
@@ -215,6 +326,7 @@ let rpService = (function() {
 
       case "sessionstore-windows-restored":
         showWelcomeWindow();
+        DetectorForOtherInstallations.checkForOtherInstallations();
         break;
 
       // support for old browsers (Firefox <20)
diff --git a/src/content/multiple-installations.html b/src/content/multiple-installations.html
new file mode 100644
index 0000000..c7b72d2
--- /dev/null
+++ b/src/content/multiple-installations.html
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+  <head>
+    <title>RequestPolicy - Multiple Installations!</title>
+    <style type="text/css">
+      body {
+        background: #fec;
+        font-family: sans-serif;
+      }
+
+      #content {
+        background-image: url(chrome://rpcontinued/skin/requestpolicy-icon-32.png);
+        background-position: 16px 3.3em;
+        background-repeat: no-repeat;
+        max-width: 45em;
+        padding: 3em 3em 3em 72px;
+      }
+
+      h1 {
+        margin-top: 0;
+      }
+
+      h1 span {
+        color: #c32;
+        font-size: 0.7em;
+      }
+
+      li {
+        margin: 1em 0;
+      }
+
+      #additional-note {
+        font-size: 0.8em;
+        margin-top: 4em;
+      }
+    </style>
+  </head>
+  <body>
+    <div id="content">
+      <h1>Important Notice! <span>regarding RequestPolicy</span></h1>
+
+      <p>
+        Multiple versions of <i>RequestPolicy</i> are installed
+        and enabled in your browser. <b>This will lead to conflicts!</b>
+      </p>
+
+      <p>
+        Therefore, please follow these steps:
+      </p>
+
+      <ol>
+        <li>
+          Make sure that only <b>one version</b> of <i>RequestPolicy</i> is installed
+          and enabled. You can disable other versions in the
+          <a href="about:addons">Add-ons Manager</a>.
+        </li>
+        <li><b>Close</b> this tab and <b>restart</b> your browser.</li>
+        <li>
+          If this tab does not open again, you're done. Otherwise you need
+          to re-check the Add-ons Manager.
+        </li>
+      </ol>
+
+      <p>
+        Sorry for the inconveniences.
+      </p>
+
+      <div id="additional-note">
+        <p>
+          <b>Note:</b> this is a static page, so it won't update even if you've
+          fixed the problem. Simply close this tab when you're finished.
+        </p>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/tests/marionette/tests/manifest.ini b/tests/marionette/tests/manifest.ini
index 042c15e..fc6bc1b 100644
--- a/tests/marionette/tests/manifest.ini
+++ b/tests/marionette/tests/manifest.ini
@@ -1,2 +1,3 @@
 [test_restartlessness.py]
 [test_setup_page.py]
+[test_multiple_installations.py]
diff --git a/tests/marionette/tests/test_multiple_installations.py b/tests/marionette/tests/test_multiple_installations.py
new file mode 100644
index 0000000..68be206
--- /dev/null
+++ b/tests/marionette/tests/test_multiple_installations.py
@@ -0,0 +1,167 @@
+# 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/.
+
+from rp_ui_harness import RequestPolicyTestCase
+from rp_puppeteer.ui.addons import RequestPolicy, Addons
+
+from rp_puppeteer.api.error_detection import (LoggingErrorDetection,
+                                              ConsoleErrorDetection)
+
+
+OLD_VERSION__ADDON_ID = "requestpolicy at requestpolicy.com"
+AMO_VERSION__ADDON_ID = "rpcontinued at requestpolicy.org"
+
+def _install_url(filename):
+    return "http://localhost/link.html?.dist/" + filename
+
+OLD_VERSION__INSTALL_URL = _install_url("requestpolicy-v1.0.beta9.3.xpi")
+AMO_VERSION__INSTALL_URL = _install_url("requestpolicy-amo.xpi")
+
+
+NOTICE_URL = "chrome://rpcontinued/content/multiple-installations.html"
+
+
+class MultipleInstallationsTestCase(RequestPolicyTestCase):
+    def setUp(self):
+        RequestPolicyTestCase.setUp(self)
+        self.rp = RequestPolicy(lambda: self.marionette)
+        self.addons = Addons(lambda: self.marionette)
+
+    def tearDown(self):
+        self._close_notice_tabs()
+        # Restart the browser. (It's a method of FirefoxTestCase.)
+        # It's necessary to restart because multiple installed versions
+        # might have broken RequestPolicy's functionality.
+        self.restart()
+        RequestPolicyTestCase.tearDown(self)
+
+    def _get_notice_tabs(self):
+        tabs = self.browser.tabbar.tabs
+        notice_tabs = []
+        for tab in tabs:
+            if tab.location == NOTICE_URL:
+                notice_tabs.append(tab)
+        return notice_tabs
+
+    @property
+    def _notice_tab(self):
+        sel_tab = self.browser.tabbar.selected_tab
+        if sel_tab.location == NOTICE_URL:
+            return sel_tab
+        notice_tabs = self._get_notice_tabs()
+        if len(notice_tabs) > 0:
+            return notice_tabs[0]
+        return None
+
+    def _assert_notice_tab(self, selected_required=True):
+        tab = self._notice_tab
+        self.assertIsNotNone(tab, msg=("The 'multiple installations notice' "
+                                       "tab has been opened."))
+
+        if selected_required:
+            self.assertTrue(tab.selected,
+                            msg=("The 'multiple installations notice' tab "
+                                 "has been selected."))
+        else:
+            tab.select()
+
+        with self.marionette.using_context("content"):
+            # check if the word "Notice" is on the page
+            notice = self.marionette.find_element(
+                "xpath",
+                "//*[contains(text(),'Notice')]")
+
+    def _close_notice_tabs(self):
+        tabs = self._get_notice_tabs()
+        for tab in tabs:
+            tab.close()
+
+
+class OldVersionTestCase(MultipleInstallationsTestCase):
+    INSTALL_URL = OLD_VERSION__INSTALL_URL
+    ADDON_ID = OLD_VERSION__ADDON_ID
+    def tearDown(self):
+        self.addons.remove_addon_by_id(self.ADDON_ID)
+        MultipleInstallationsTestCase.tearDown(self)
+
+
+class TestOldVersionActive_ThenInstallCurrentVersion(OldVersionTestCase):
+    def setUp(self):
+        OldVersionTestCase.setUp(self)
+        self.rp.remove()
+        self.addons.install_addon(self.INSTALL_URL)
+
+    def test_notice_is_shown(self):
+        with self.rp.install_in_two_steps():
+            self._assert_notice_tab()
+
+class TestOldVersionActive_ThenEnableCurrentVersion(OldVersionTestCase):
+    def setUp(self):
+        OldVersionTestCase.setUp(self)
+        self.rp.disable()
+        self.addons.install_addon(self.INSTALL_URL)
+
+    def test_notice_is_shown(self):
+        self.rp.enable()
+        self._assert_notice_tab()
+
+class TestOldVersionNotActive_ThenInstall(OldVersionTestCase):
+    def test_notice_is_shown(self):
+        with self.addons.install_addon_in_two_steps(self.INSTALL_URL):
+            self._assert_notice_tab()
+
+class TestOldVersionNotActive_ThenEnable(OldVersionTestCase):
+    def setUp(self):
+        OldVersionTestCase.setUp(self)
+        # After this preparation, both the current and the old version
+        # will be installed, but the old version will be disabled.
+        self.rp.disable()
+        self.addons.install_addon(self.INSTALL_URL)
+        self.addons.disable_addon_by_id(self.ADDON_ID)
+        self.rp.enable()
+        self.assertIsNone(self._notice_tab,
+                          msg=("No 'notice' tab has been opened during "
+                               "preparation"))
+
+    def test_notice_is_shown(self):
+        self.addons.enable_addon_by_id(self.ADDON_ID)
+        self._assert_notice_tab()
+
+class TestOldAndCurrentVersionActiveAfterRestart(OldVersionTestCase):
+    def setUp(self):
+        OldVersionTestCase.setUp(self)
+        self.addons.install_addon(self.INSTALL_URL)
+        self._close_notice_tabs()
+
+    def test_notice_is_shown(self):
+        self.restart()
+        # Don't require the tab to be selected. It somehow doesn't get
+        # selected in the unit test, but it works when done manually.
+        self._assert_notice_tab(selected_required=False)
+
+
+class TestAMOVersionActive_ThenInstallCurrentVersion( \
+        TestOldVersionActive_ThenInstallCurrentVersion):
+    INSTALL_URL = AMO_VERSION__INSTALL_URL
+    ADDON_ID = AMO_VERSION__ADDON_ID
+
+class TestAMOVersionActive_ThenEnableCurrentVersion( \
+        TestOldVersionActive_ThenEnableCurrentVersion):
+    INSTALL_URL = AMO_VERSION__INSTALL_URL
+    ADDON_ID = AMO_VERSION__ADDON_ID
+
+class TestAMOVersionNotActive_ThenInstall( \
+        TestOldVersionNotActive_ThenInstall):
+    INSTALL_URL = AMO_VERSION__INSTALL_URL
+    ADDON_ID = AMO_VERSION__ADDON_ID
+
+class TestAMOVersionNotActive_ThenEnable( \
+        TestOldVersionNotActive_ThenEnable):
+    INSTALL_URL = AMO_VERSION__INSTALL_URL
+    ADDON_ID = AMO_VERSION__ADDON_ID
+
+class TestAMOAndNonAMOVersionActiveAfterRestart( \
+        TestOldAndCurrentVersionActiveAfterRestart):
+    INSTALL_URL = AMO_VERSION__INSTALL_URL
+    ADDON_ID = AMO_VERSION__ADDON_ID

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/requestpolicy.git



More information about the Pkg-mozext-commits mailing list