Bug 1442179 - If the user enters something that can not be parsed as a URL, appends http:// and https:// and adds permission for both of them. r=johannh
authorCarolina Jimenez Gomez <carolina.jimenez.g@gmail.com>
Tue, 19 Mar 2019 14:14:03 +0000
changeset 465105 6e305e6f45432091b99a29f57a7aaffc00ac0ddf
parent 465104 a490015d86a694fe33003ccaf19b0924f7533d63
child 465106 8d9b4e8dce578a417cc0f2f98eaebe3cef47370f
push id35732
push useropoprus@mozilla.com
push dateWed, 20 Mar 2019 10:52:37 +0000
treeherdermozilla-central@708979f9c3f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjohannh
bugs1442179
milestone68.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 1442179 - If the user enters something that can not be parsed as a URL, appends http:// and https:// and adds permission for both of them. r=johannh Differential Revision: https://phabricator.services.mozilla.com/D21138
browser/components/preferences/in-content/tests/browser.ini
browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
browser/components/preferences/in-content/tests/browser_permissions_checkPermissionsWereAdded.js
browser/components/preferences/in-content/tests/browser_site_login_exceptions.js
browser/components/preferences/permissions.js
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -64,16 +64,17 @@ skip-if = (!debug && os == 'win') # Bug 
 [browser_notifications_do_not_disturb.js]
 [browser_password_management.js]
 [browser_performance.js]
 skip-if = !e10s
 [browser_performance_e10srollout.js]
 skip-if = !e10s
 [browser_performance_non_e10s.js]
 skip-if = e10s
+[browser_permissions_checkPermissionsWereAdded.js]
 [browser_permissions_urlFieldHidden.js]
 [browser_proxy_backup.js]
 [browser_privacypane_2.js]
 [browser_privacypane_3.js]
 [browser_sanitizeOnShutdown_prefLocked.js]
 [browser_searchShowSuggestionsFirst.js]
 [browser_searchsuggestions.js]
 [browser_security-1.js]
--- a/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
+++ b/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
@@ -7,194 +7,270 @@ add_task(async function testAllow() {
   await runTest(async (params, observeAllPromise, apply) => {
     assertListContents(params, []);
 
     params.url.value = "test.com";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["http://test.com", params.allowL10nId],
+      ["https://test.com", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://test.com", data: "added",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://test.com", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+            { type: "cookie", origin: "https://test.com", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testBlock() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "test.com";
     params.btnBlock.doCommand();
 
     assertListContents(params, [
       ["http://test.com", params.denyL10nId],
+      ["https://test.com", params.denyL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://test.com", data: "changed",
-        capability: Ci.nsIPermissionManager.DENY_ACTION  }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://test.com", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  },
+            { type: "cookie", origin: "https://test.com", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  }];
+  });
 });
 
 add_task(async function testAllowAgain() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "test.com";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["http://test.com", params.allowL10nId],
+      ["https://test.com", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://test.com", data: "changed",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://test.com", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+            { type: "cookie", origin: "https://test.com", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testRemove() {
   await runTest(async (params, observeAllPromise, apply) => {
-    params.richlistbox.selectedIndex = 0;
-    params.btnRemove.doCommand();
-
+    while (params.richlistbox.itemCount) {
+      params.richlistbox.selectedIndex = 0;
+      params.btnRemove.doCommand();
+    }
     assertListContents(params, []);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://test.com", data: "deleted" }]);
+  }, (params) => {
+    let richlistItems = params.richlistbox.getElementsByAttribute("origin", "*");
+    let observances = [];
+    for (let item of richlistItems) {
+      observances.push({
+        type: "cookie",
+        origin: item.getAttribute("origin"),
+        data: "deleted",
+      });
+    }
+    return observances;
+  });
 });
 
 add_task(async function testAdd() {
   await runTest(async (params, observeAllPromise, apply) => {
     let uri = Services.io.newURI("http://test.com");
     Services.perms.add(uri, "popup", Ci.nsIPermissionManager.DENY_ACTION);
 
     info("Adding unrelated permission should not change display.");
     assertListContents(params, []);
 
     apply();
     await observeAllPromise;
 
     Services.perms.remove(uri, "popup");
-  }, [{ type: "popup", origin: "http://test.com", data: "added",
-        capability: Ci.nsIPermissionManager.DENY_ACTION }]);
+  }, (params) => {
+    return [{ type: "popup", origin: "http://test.com", data: "added",
+              capability: Ci.nsIPermissionManager.DENY_ACTION }];
+  });
 });
 
 add_task(async function testAllowHTTPSWithPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "https://test.com:12345";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["https://test.com:12345", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "https://test.com:12345", data: "added",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "https://test.com:12345", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testBlockHTTPSWithPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "https://test.com:12345";
     params.btnBlock.doCommand();
 
     assertListContents(params, [
       ["https://test.com:12345", params.denyL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
-        capability: Ci.nsIPermissionManager.DENY_ACTION  }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  }];
+  });
 });
 
 add_task(async function testAllowAgainHTTPSWithPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "https://test.com:12345";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["https://test.com:12345", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testRemoveHTTPSWithPort() {
   await runTest(async (params, observeAllPromise, apply) => {
-    params.richlistbox.selectedIndex = 0;
-    params.btnRemove.doCommand();
+    while (params.richlistbox.itemCount) {
+      params.richlistbox.selectedIndex = 0;
+      params.btnRemove.doCommand();
+    }
 
     assertListContents(params, []);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "https://test.com:12345", data: "deleted" }]);
+  }, (params) => {
+    let richlistItems = params.richlistbox.getElementsByAttribute("origin", "*");
+    let observances = [];
+    for (let item of richlistItems) {
+      observances.push({
+        type: "cookie",
+        origin: item.getAttribute("origin"),
+        data: "deleted",
+      });
+    }
+    return observances;
+  });
 });
 
 add_task(async function testAllowPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "localhost:12345";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["http://localhost:12345", params.allowL10nId],
+      ["https://localhost:12345", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://localhost:12345", data: "added",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://localhost:12345", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+            { type: "cookie", origin: "https://localhost:12345", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testBlockPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "localhost:12345";
     params.btnBlock.doCommand();
 
     assertListContents(params, [
       ["http://localhost:12345", params.denyL10nId],
+      ["https://localhost:12345", params.denyL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
-        capability: Ci.nsIPermissionManager.DENY_ACTION  }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  },
+            { type: "cookie", origin: "https://localhost:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  }];
+  });
 });
 
 add_task(async function testAllowAgainPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "localhost:12345";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["http://localhost:12345", params.allowL10nId],
+      ["https://localhost:12345", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+            { type: "cookie", origin: "https://localhost:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testRemovePort() {
   await runTest(async (params, observeAllPromise, apply) => {
-    params.richlistbox.selectedIndex = 0;
-    params.btnRemove.doCommand();
+    while (params.richlistbox.itemCount) {
+      params.richlistbox.selectedIndex = 0;
+      params.btnRemove.doCommand();
+    }
 
     assertListContents(params, []);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://localhost:12345", data: "deleted" }]);
+  }, (params) => {
+    let richlistItems = params.richlistbox.getElementsByAttribute("origin", "*");
+    let observances = [];
+    for (let item of richlistItems) {
+      observances.push({
+        type: "cookie",
+        origin: item.getAttribute("origin"),
+        data: "deleted",
+      });
+    }
+    return observances;
+  });
 });
 
 add_task(async function testSort() {
   await runTest(async (params, observeAllPromise, apply) => {
     // Sort by site name.
     EventUtils.synthesizeMouseAtCenter(params.doc.getElementById("siteCol"), {},
                                        params.doc.defaultView);
 
@@ -221,37 +297,39 @@ add_task(async function testSort() {
 
     apply();
     await observeAllPromise;
 
     for (let URL of ["http://a", "http://z", "http://b"]) {
       let uri = Services.io.newURI(URL);
       Services.perms.remove(uri, "cookie");
     }
-  }, [{ type: "cookie", origin: "http://a", data: "added",
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://a", data: "added",
         capability: Ci.nsIPermissionManager.ALLOW_ACTION },
       { type: "cookie", origin: "http://z", data: "added",
         capability: Ci.nsIPermissionManager.ALLOW_ACTION },
       { type: "cookie", origin: "http://b", data: "added",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+        capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 function assertListContents(params, expected) {
   Assert.equal(params.richlistbox.itemCount, expected.length);
+
   for (let i = 0; i < expected.length; i++) {
-    let richlistitem = params.richlistbox.getItemAtIndex(i);
-    Assert.equal(richlistitem.getAttribute("origin"), expected[i][0]);
-    Assert.equal(richlistitem.querySelector(".website-name > label")
-                             .getAttribute("value"), expected[i][0]);
-    Assert.equal(richlistitem.querySelector(".website-capability-value")
+    let website = expected[i][0];
+    let elements = params.richlistbox.getElementsByAttribute("origin", website);
+    Assert.equal(elements.length, 1); // "It should find only one coincidence"
+    Assert.equal(elements[0].querySelector(".website-capability-value")
                              .getAttribute("data-l10n-id"), expected[i][1]);
   }
 }
 
-async function runTest(test, observances) {
+async function runTest(test, getObservances) {
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("privacy.history.custom");
   });
 
   await openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
 
   let doc = gBrowser.contentDocument;
   let historyMode = doc.getElementById("historyMode");
@@ -273,16 +351,17 @@ async function runTest(test, observances
     btnBlock: doc.getElementById("btnBlock"),
     btnRemove: doc.getElementById("removePermission"),
     allowL10nId: win.gPermissionManager._getCapabilityL10nId(Ci.nsIPermissionManager.ALLOW_ACTION),
     denyL10nId: win.gPermissionManager._getCapabilityL10nId(Ci.nsIPermissionManager.DENY_ACTION),
     allow: Ci.nsIPermissionManager.ALLOW_ACTION,
     deny: Ci.nsIPermissionManager.DENY_ACTION,
   };
   let btnApplyChanges = doc.getElementById("btnApplyChanges");
+  let observances = getObservances(params);
   let observeAllPromise = createObserveAllPromise(observances);
 
   await test(params, observeAllPromise, () => btnApplyChanges.doCommand());
 
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 }
 
 function createObserveAllPromise(observances) {
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_permissions_checkPermissionsWereAdded.js
@@ -0,0 +1,102 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const PERMISSIONS_URL = "chrome://browser/content/preferences/permissions.xul";
+
+const _checkAndOpenCookiesDialog = async (doc) => {
+  let cookieExceptionsButton = doc.getElementById("cookieExceptions");
+  ok(cookieExceptionsButton, "cookieExceptionsButton found");
+  let dialogPromise = promiseLoadSubDialog(PERMISSIONS_URL);
+  cookieExceptionsButton.click();
+  let dialog = await dialogPromise;
+  return dialog;
+};
+
+const _checkCookiesDialog = (dialog, buttonIds) => {
+  ok(dialog, "dialog loaded");
+  let urlLabel = dialog.document.getElementById("urlLabel");
+  ok(!urlLabel.hidden, "urlLabel should be visible");
+  let url = dialog.document.getElementById("url");
+  ok(!url.hidden, "url should be visible");
+  for (let buttonId of buttonIds) {
+    let buttonDialog = dialog.document.getElementById(buttonId);
+    ok(buttonDialog, "blockButtonDialog found");
+    is(buttonDialog.hasAttribute("disabled"), true, "If the user hasn't added an url the button shouldn't be clickable");
+  }
+  return dialog;
+};
+
+const _addWebsiteAddressToPermissionBox = (websiteAddress, dialog, buttonId) => {
+  let url = dialog.document.getElementById("url");
+  let buttonDialog = dialog.document.getElementById(buttonId);
+  url.value = websiteAddress;
+  url.dispatchEvent(new Event("input", {bubbles: true}));
+  is(buttonDialog.hasAttribute("disabled"), false, "When the user add an url the button should be clickable");
+  buttonDialog.click();
+  let permissionsBox = dialog.document.getElementById("permissionsBox");
+  let children = permissionsBox.getElementsByAttribute("origin", "*");
+  is(children.length == 0, false, "Website added in url should be in the list");
+};
+
+const _checkIfPermissionsWereAdded = (dialog, expectedResult) => {
+  let permissionsBox = dialog.document.getElementById("permissionsBox");
+  for (let website of expectedResult) {
+    let elements = permissionsBox.getElementsByAttribute("origin", website);
+    is(elements.length, 1, "It should find only one coincidence");
+  }
+};
+
+const _removesAllSitesInPermissionBox = (dialog) => {
+  let removeAllWebsitesButton = dialog.document.getElementById("removeAllPermissions");
+  ok(removeAllWebsitesButton, "removeAllWebsitesButton found");
+  is(removeAllWebsitesButton.hasAttribute("disabled"), false, "There should be websites in the list");
+  removeAllWebsitesButton.click();
+};
+
+add_task(async function checkCookiePermissions() {
+  await openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
+  let win = gBrowser.selectedBrowser.contentWindow;
+  let doc = win.document;
+  let buttonIds = ["btnBlock", "btnSession", "btnAllow"];
+
+  let dialog = await _checkAndOpenCookiesDialog(doc);
+  _checkCookiesDialog(dialog, buttonIds);
+
+  let tests = [{
+      "inputWebsite": "google.com",
+      "expectedResult": ["http://google.com", "https://google.com"],
+    },
+    {
+      "inputWebsite": "https://google.com",
+      "expectedResult": ["https://google.com"],
+    },
+    {
+      "inputWebsite": "http://",
+      "expectedResult": ["http://http", "https://http"],
+    },
+    {
+      "inputWebsite": "s3.eu-central-1.amazonaws.com",
+      "expectedResult": ["http://s3.eu-central-1.amazonaws.com", "https://s3.eu-central-1.amazonaws.com"],
+    },
+    {
+      "inputWebsite": "file://",
+      "expectedResult": ["file:///"],
+    },
+    {
+      "inputWebsite": "about:config",
+      "expectedResult": ["about:config"],
+    },
+  ];
+
+  for (let buttonId of buttonIds) {
+    for (let test of tests) {
+      _addWebsiteAddressToPermissionBox(test.inputWebsite, dialog, buttonId);
+      _checkIfPermissionsWereAdded(dialog, test.expectedResult);
+      _removesAllSitesInPermissionBox(dialog);
+    }
+  }
+
+  gBrowser.removeCurrentTab();
+});
--- a/browser/components/preferences/in-content/tests/browser_site_login_exceptions.js
+++ b/browser/components/preferences/in-content/tests/browser_site_login_exceptions.js
@@ -44,33 +44,42 @@ add_task(async function addALoginExcepti
   let inputBox = doc.getElementById("url");
   inputBox.focus();
 
   EventUtils.sendString("www.example.com", exceptionsDialog);
 
   let btnBlock = doc.getElementById("btnBlock");
   btnBlock.click();
 
-  await TestUtils.waitForCondition(() => richlistbox.itemCount == 1);
+  await TestUtils.waitForCondition(() => richlistbox.itemCount == 2);
 
-  Assert.equal(richlistbox.getItemAtIndex(0).getAttribute("origin"),
-               "http://www.example.com");
+  let expectedResult = ["http://www.example.com", "https://www.example.com"];
+  for (let website of expectedResult) {
+    let elements = richlistbox.getElementsByAttribute("origin", website);
+    is(elements.length, 1, "It should find only one coincidence");
+  }
 });
 
 add_task(async function deleteALoginException() {
   let doc = exceptionsDialog.document;
 
   let richlistbox = doc.getElementById("permissionsBox");
-  Assert.equal(richlistbox.itemCount, 1, "Row count should initially be 1");
+  let currentItems = 2;
+  Assert.equal(richlistbox.itemCount, currentItems,
+               `Row count should initially be ${currentItems}`);
   richlistbox.focus();
-  richlistbox.selectedIndex = 0;
+
+  while (richlistbox.itemCount) {
+    richlistbox.selectedIndex = 0;
 
-  if (AppConstants.platform == "macosx") {
-    EventUtils.synthesizeKey("KEY_Backspace");
-  } else {
-    EventUtils.synthesizeKey("KEY_Delete");
-  }
+    if (AppConstants.platform == "macosx") {
+      EventUtils.synthesizeKey("KEY_Backspace");
+    } else {
+      EventUtils.synthesizeKey("KEY_Delete");
+    }
 
-  await TestUtils.waitForCondition(() => richlistbox.itemCount == 0);
+    currentItems -= 1;
 
-  is_element_visible(content.gSubDialog._dialogs[0]._box,
-    "Subdialog is visible after deleting an element");
+    await TestUtils.waitForCondition(() => richlistbox.itemCount == currentItems);
+    is_element_visible(content.gSubDialog._dialogs[0]._box,
+      "Subdialog is visible after deleting an element");
+  }
 });
--- a/browser/components/preferences/permissions.js
+++ b/browser/components/preferences/permissions.js
@@ -178,62 +178,72 @@ var gPermissionManager = {
       return;
     if (!this._isCapabilitySupported(perm.capability))
       return;
 
     let p = new Permission(perm.principal, perm.type, perm.capability);
     this._permissions.set(p.origin, p);
   },
 
+  _addOrModifyPermission(principal, capability) {
+    // check whether the permission already exists, if not, add it
+    let permissionParams = {principal, type: this._type, capability};
+    let existingPermission = this._permissions.get(principal.origin);
+    if (!existingPermission) {
+      this._permissionsToAdd.set(principal.origin, permissionParams);
+      this._addPermissionToList(permissionParams);
+      this.buildPermissionsList();
+    } else if (existingPermission.capability != capability) {
+      existingPermission.capability = capability;
+      this._permissionsToAdd.set(principal.origin, permissionParams);
+      this._handleCapabilityChange(existingPermission);
+    }
+  },
+
+  _addNewPrincipalToList(list, uri) {
+    list.push(Services.scriptSecurityManager.createCodebasePrincipal(uri, {}));
+    // If we have ended up with an unknown scheme, the following will throw.
+    list[list.length - 1].origin;
+  },
+
   addPermission(capability) {
     let textbox = document.getElementById("url");
     let input_url = textbox.value.replace(/^\s*/, ""); // trim any leading space
-    let principal;
+    let principals = [];
     try {
       // The origin accessor on the principal object will throw if the
       // principal doesn't have a canonical origin representation. This will
       // help catch cases where the URI parser parsed something like
       // `localhost:8080` as having the scheme `localhost`, rather than being
       // an invalid URI. A canonical origin representation is required by the
       // permission manager for storage, so this won't prevent any valid
       // permissions from being entered by the user.
-      let uri;
       try {
-        uri = Services.io.newURI(input_url);
-        principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
+        let uri = Services.io.newURI(input_url);
+        let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
         if (principal.origin.startsWith("moz-nullprincipal:")) {
           throw "Null principal";
         }
+        principals.push(principal);
       } catch (ex) {
-        uri = Services.io.newURI("http://" + input_url);
-        principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
-        // If we have ended up with an unknown scheme, the following will throw.
-        principal.origin;
+        this._addNewPrincipalToList(principals, Services.io.newURI("http://" + input_url));
+        this._addNewPrincipalToList(principals, Services.io.newURI("https://" + input_url));
       }
     } catch (ex) {
       document.l10n.formatValues([
         {id: "permissions-invalid-uri-title"},
         {id: "permissions-invalid-uri-label"},
       ]).then(([title, message]) => {
         Services.prompt.alert(window, title, message);
       });
       return;
     }
 
-    // check whether the permission already exists, if not, add it
-    let permissionParams = {principal, type: this._type, capability};
-    let existingPermission = this._permissions.get(principal.origin);
-    if (!existingPermission) {
-      this._permissionsToAdd.set(principal.origin, permissionParams);
-      this._addPermissionToList(permissionParams);
-      this.buildPermissionsList();
-    } else if (existingPermission.capability != capability) {
-      existingPermission.capability = capability;
-      this._permissionsToAdd.set(principal.origin, permissionParams);
-      this._handleCapabilityChange(existingPermission);
+    for (let principal of principals) {
+      this._addOrModifyPermission(principal, capability);
     }
 
     textbox.value = "";
     textbox.focus();
 
     // covers a case where the site exists already, so the buttons don't disable
     this.onHostInput(textbox);