Backed out 24 changesets (bug 1173523, bug 1172080, bug 817007, bug 1165263) for android reftest bustage CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Tue, 14 Jul 2015 14:00:32 -0700
changeset 286210 de3fb216f066feea0024104288db95b97e514b39
parent 286209 1a4ac9e6d911fbd8561f91d01fd6c022e802a126
child 286211 22e8c544040543b89df9c046079553f861faf846
push id934
push userraliiev@mozilla.com
push dateMon, 26 Oct 2015 12:58:05 +0000
treeherdermozilla-release@05704e35c1d0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1173523, 1172080, 817007, 1165263
milestone42.0a1
backs out84fe04b2e7d15f1dd7779996001e6b2e5d7df342
0ff004760a1ff67fdce8b410910001b6fdbdfc06
af147585ad5591a0175966f655dce16110e81165
c3af8ebb6db05bcd0c0d8384480aa3047fec423f
cd3f33a888fe187c62ea42e469f9ae0b8b158afb
e5db39044a1e9bc3b359917ebc0fb824aaf4de6c
c01c9ed77061775552cf7b9d7484880d9ce931d7
fb723aaa42678639f6f11709f2a75b042eca3a52
f754e52e74dc1a48564b81efd1a8fe94479d450d
c6bda3a0afd6edd9e0eb8370f4af5d46793da2d2
bfa100253349f353401e83107a095faa3e6dcb00
b787b3f9aadc0b6fe0e75d7291976fac1803c33b
4a0676b73f77cd046c4620da0ceecbc4d49e3c9e
82034a4560c5e568c6dc8ebe487e470e227b86ed
4bdb91114c7a64c97629eb31383ed6365a5a7654
72406261eccc5739cb5572dd56cd5873758da33c
541b6faf71965678dd516bdd05d3cfcc94428e6d
1caac45696160b89a1b849757bc523e73e7b35d0
0d4f9f9e1b4ec576846dcde0a806cccae29ec500
2d5661eb966c6a71c4e83e341ccbd32911b76aac
89833c0bb0cd567b104335fc39747e5a611c4dc8
ea64d70eacfe35a92b49fccf504320bf17562bf6
a8e4f1c0c4458d83c72553e31a41f506bbfd3f6f
cf498d466b85edd8067efafa2cffd3f5beb33747
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
Backed out 24 changesets (bug 1173523, bug 1172080, bug 817007, bug 1165263) for android reftest bustage CLOSED TREE Backed out changeset 84fe04b2e7d1 (bug 1172080) Backed out changeset 0ff004760a1f (bug 1172080) Backed out changeset af147585ad55 (bug 1165263) Backed out changeset c3af8ebb6db0 (bug 1165263) Backed out changeset cd3f33a888fe (bug 1165263) Backed out changeset e5db39044a1e (bug 1165263) Backed out changeset c01c9ed77061 (bug 1165263) Backed out changeset fb723aaa4267 (bug 1165263) Backed out changeset f754e52e74dc (bug 1165263) Backed out changeset c6bda3a0afd6 (bug 817007) Backed out changeset bfa100253349 (bug 817007) Backed out changeset b787b3f9aadc (bug 1173523) Backed out changeset 4a0676b73f77 (bug 1173523) Backed out changeset 82034a4560c5 (bug 1173523) Backed out changeset 4bdb91114c7a (bug 1173523) Backed out changeset 72406261eccc (bug 1173523) Backed out changeset 541b6faf7196 (bug 1173523) Backed out changeset 1caac4569616 (bug 1173523) Backed out changeset 0d4f9f9e1b4e (bug 1173523) Backed out changeset 2d5661eb966c (bug 1173523) Backed out changeset 89833c0bb0cd (bug 1173523) Backed out changeset ea64d70eacfe (bug 1173523) Backed out changeset a8e4f1c0c445 (bug 1173523) Backed out changeset cf498d466b85 (bug 1173523)
browser/app/permissions
browser/base/content/browser-plugins.js
browser/base/content/browser-trackingprotection.js
browser/base/content/pageinfo/pageInfo.js
browser/base/content/pageinfo/permissions.js
browser/base/content/test/general/browser_bug592338.js
browser/base/content/test/plugins/head.js
browser/base/content/urlbarBindings.xml
browser/components/preferences/aboutPermissions.js
browser/components/preferences/advanced.js
browser/components/preferences/in-content/advanced.js
browser/components/preferences/permissions.js
browser/components/preferences/tests/browser_chunk_permissions.js
browser/components/preferences/tests/browser_cookies_exceptions.js
browser/components/preferences/tests/browser_permissions.js
browser/components/preferences/translation.js
browser/components/translation/test/browser_translation_exceptions.js
browser/components/uitour/test/head.js
browser/modules/PluginContent.jsm
caps/BasePrincipal.cpp
caps/nsPrincipal.cpp
caps/tests/unit/test_origin.js
dom/apps/tests/unit/test_moziapplication.js
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/storage/DOMStorageObserver.cpp
extensions/cookie/nsPermission.cpp
extensions/cookie/nsPermission.h
extensions/cookie/nsPermissionManager.cpp
extensions/cookie/nsPermissionManager.h
extensions/cookie/test/test_app_uninstall_permissions.html
extensions/cookie/test/unit/test_permmanager_defaults.js
extensions/cookie/test/unit/test_permmanager_getPermissionObject.js
extensions/cookie/test/unit/test_permmanager_load_invalid_entries.js
extensions/cookie/test/unit/test_permmanager_local_files.js
extensions/cookie/test/unit/test_permmanager_mailto.js
extensions/cookie/test/unit/test_permmanager_matches.js
extensions/cookie/test/unit/test_permmanager_matchesuri.js
extensions/cookie/test/unit/test_permmanager_migrate_4-5.js
extensions/cookie/test/unit/xpcshell.ini
layout/tools/reftest/reftest-preferences.js
layout/tools/reftest/reftest.js
layout/tools/reftest/remotereftest.py
layout/tools/reftest/runreftest.py
mobile/android/app/mobile.js
mobile/android/chrome/content/browser.js
netwerk/base/nsIPermission.idl
netwerk/ipc/NeckoMessageUtils.h
netwerk/test/unit/test_permmgr.js
testing/mozbase/mozprofile/mozprofile/permissions.py
testing/mozbase/mozprofile/tests/bug785146.py
testing/mozbase/mozprofile/tests/permissions.py
testing/specialpowers/components/SpecialPowersObserver.js
testing/specialpowers/content/specialpowersAPI.js
toolkit/forgetaboutsite/ForgetAboutSite.jsm
toolkit/modules/BrowserUtils.jsm
toolkit/modules/PermissionsUtils.jsm
toolkit/modules/tests/xpcshell/test_PermissionsUtils.js
toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js
--- a/browser/app/permissions
+++ b/browser/app/permissions
@@ -1,21 +1,21 @@
 # This file has default permissions for the permission manager.
 # The file-format is strict:
 # * matchtype \t type \t permission \t host
-# * "origin" should be used for matchtype, "host" is supported for legacy reasons
+# * Only "host" is supported for matchtype
 # * type is a string that identifies the type of permission (e.g. "cookie")
 # * permission is an integer between 1 and 15
 # See nsPermissionManager.cpp for more...
 
 # UITour
-origin	uitour	1	https://www.mozilla.org
-origin	uitour	1	https://self-repair.mozilla.org
-origin	uitour	1	https://support.mozilla.org
-origin	uitour	1	about:home
+host	uitour	1	www.mozilla.org
+host	uitour	1	self-repair.mozilla.org
+host	uitour	1	support.mozilla.org
+host	uitour	1	about:home
 
 # XPInstall
-origin	install	1	https://addons.mozilla.org
-origin	install	1	https://marketplace.firefox.com
+host	install	1	addons.mozilla.org
+host	install	1	marketplace.firefox.com
 
 # Remote troubleshooting
-origin	remote-troubleshooting	1	https://input.mozilla.org
-origin	remote-troubleshooting	1	https://support.mozilla.org
+host	remote-troubleshooting	1	input.mozilla.org
+host	remote-troubleshooting	1	support.mozilla.org
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -39,24 +39,24 @@ var gPluginHandler = {
       this.uninit();
     }
   },
 
   receiveMessage: function (msg) {
     switch (msg.name) {
       case "PluginContent:ShowClickToPlayNotification":
         this.showClickToPlayNotification(msg.target, msg.data.plugins, msg.data.showNow,
-                                         msg.principal, msg.data.location);
+                                         msg.principal, msg.data.host, msg.data.location);
         break;
       case "PluginContent:RemoveNotification":
         this.removeNotification(msg.target, msg.data.name);
         break;
       case "PluginContent:UpdateHiddenPluginUI":
         this.updateHiddenPluginUI(msg.target, msg.data.haveInsecure, msg.data.actions,
-                                  msg.principal, msg.data.location);
+                                  msg.principal, msg.data.host, msg.data.location);
         break;
       case "PluginContent:HideNotificationBar":
         this.hideNotificationBar(msg.target, msg.data.name);
         break;
       case "PluginContent:ShowInstallNotification":
         return this.showInstallNotification(msg.target, msg.data.pluginInfo);
       case "PluginContent:InstallSinglePlugin":
         this.installSinglePlugin(msg.data.pluginInfo);
@@ -211,18 +211,18 @@ var gPluginHandler = {
     }
 
     browser.messageManager.sendAsyncMessage("BrowserPlugins:ActivatePlugins", {
       pluginInfo: aPluginInfo,
       newState: aNewState,
     });
   },
 
-  showClickToPlayNotification: function (browser, plugins, showNow,
-                                         principal, location) {
+  showClickToPlayNotification: function (browser, plugins, showNow, principal,
+                                         host, location) {
     // It is possible that we've received a message from the frame script to show
     // a click to play notification for a principal that no longer matches the one
     // that the browser's content now has assigned (ie, the browser has browsed away
     // after the message was sent, but before the message was received). In that case,
     // we should just ignore the message.
     if (!principal.equals(browser.contentPrincipal)) {
       return;
     }
@@ -290,16 +290,17 @@ var gPluginHandler = {
     }
 
     let options = {
       dismissed: !showNow,
       eventCallback: this._clickToPlayNotificationEventCallback,
       primaryPlugin: primaryPluginPermission,
       pluginData: pluginData,
       principal: principal,
+      host: host,
     };
     PopupNotifications.show(browser, "click-to-play-plugins",
                             "", "plugins-notification-icon",
                             null, null, options);
     browser.messageManager.sendAsyncMessage("BrowserPlugins:NotificationShown");
   },
 
   removeNotification: function (browser, name) {
@@ -310,20 +311,18 @@ var gPluginHandler = {
 
   hideNotificationBar: function (browser, name) {
     let notificationBox = gBrowser.getNotificationBox(browser);
     let notification = notificationBox.getNotificationWithValue(name);
     if (notification)
       notificationBox.removeNotification(notification, true);
   },
 
-  updateHiddenPluginUI: function (browser, haveInsecure, actions,
-                                  principal, location) {
-    let origin = principal.originNoSuffix;
-
+  updateHiddenPluginUI: function (browser, haveInsecure, actions, principal,
+                                  host, location) {
     // It is possible that we've received a message from the frame script to show
     // the hidden plugin notification for a principal that no longer matches the one
     // that the browser's content now has assigned (ie, the browser has browsed away
     // after the message was sent, but before the message was received). In that case,
     // we should just ignore the message.
     if (!principal.equals(browser.contentPrincipal)) {
       return;
     }
@@ -376,32 +375,32 @@ var gPluginHandler = {
       if (actions.length == 1) {
         let pluginInfo = actions[0];
         let pluginName = pluginInfo.pluginName;
 
         switch (pluginInfo.fallbackType) {
           case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
             message = gNavigatorBundle.getFormattedString(
               "pluginActivateNew.message",
-              [pluginName, origin]);
+              [pluginName, host]);
             break;
           case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
             message = gNavigatorBundle.getFormattedString(
               "pluginActivateOutdated.message",
-              [pluginName, origin, brand]);
+              [pluginName, host, brand]);
             break;
           case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
             message = gNavigatorBundle.getFormattedString(
               "pluginActivateVulnerable.message",
-              [pluginName, origin, brand]);
+              [pluginName, host, brand]);
         }
       } else {
         // Multi-plugin
         message = gNavigatorBundle.getFormattedString(
-          "pluginActivateMultiple.message", [origin]);
+          "pluginActivateMultiple.message", [host]);
       }
 
       let buttons = [
         {
           label: gNavigatorBundle.getString("pluginContinueBlocking.label"),
           accessKey: gNavigatorBundle.getString("pluginContinueBlocking.accesskey"),
           callback: function() {
             Services.telemetry.getHistogramById("PLUGINS_INFOBAR_BLOCK").
--- a/browser/base/content/browser-trackingprotection.js
+++ b/browser/base/content/browser-trackingprotection.js
@@ -94,21 +94,17 @@ let TrackingProtection = {
 
     BrowserReload();
   },
 
   enableForCurrentPage() {
     // Remove the current host from the 'trackingprotection' consumer
     // of the permission manager. This effectively removes this host
     // from the tracking protection allowlist.
-    let normalizedUrl = Services.io.newURI(
-      "https://" + gBrowser.selectedBrowser.currentURI.hostPort,
-      null, null);
-
-    Services.perms.remove(normalizedUrl,
+    Services.perms.remove(gBrowser.selectedBrowser.currentURI,
       "trackingprotection");
 
     // Telemetry for enable protection.
     this.eventsHistogram.add(2);
 
     BrowserReload();
   },
 };
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -1112,19 +1112,18 @@ var imagePermissionObserver = {
 
     if (aTopic == "perm-changed") {
       var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission);
       if (permission.type == "image") {
         var imageTree = document.getElementById("imagetree");
         var row = getSelectedRow(imageTree);
         var item = gImageView.data[row][COL_IMAGE_NODE];
         var url = gImageView.data[row][COL_IMAGE_ADDRESS];
-        if (permission.matchesURI(makeURI(url), true)) {
+        if (makeURI(url).host == permission.host)
           makeBlockImage(url);
-        }
       }
     }
   }
 }
 
 function getContentTypeFromHeaders(cacheEntryDescriptor)
 {
   if (!cacheEntryDescriptor)
--- a/browser/base/content/pageinfo/permissions.js
+++ b/browser/base/content/pageinfo/permissions.js
@@ -13,34 +13,34 @@ var gUsageRequest;
 var gPermissions = SitePermissions.listPermissions();
 gPermissions.push("plugins");
 
 var permissionObserver = {
   observe: function (aSubject, aTopic, aData)
   {
     if (aTopic == "perm-changed") {
       var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission);
-      if (permission.matchesURI(gPermURI, true)) {
+      if (permission.host == gPermURI.host) {
         if (gPermissions.indexOf(permission.type) > -1)
           initRow(permission.type);
         else if (permission.type.startsWith("plugin"))
           setPluginsRadioState();
       }
     }
   }
 };
 
 function onLoadPermission()
 {
   var uri = BrowserUtils.makeURIFromCPOW(gDocument.documentURIObject);
   var permTab = document.getElementById("permTab");
   if (SitePermissions.isSupportedURI(uri)) {
     gPermURI = uri;
     var hostText = document.getElementById("hostText");
-    hostText.value = gPermURI.prePath;
+    hostText.value = gPermURI.host;
 
     for (var i of gPermissions)
       initRow(i);
     var os = Components.classes["@mozilla.org/observer-service;1"]
                        .getService(Components.interfaces.nsIObserverService);
     os.addObserver(permissionObserver, "perm-changed", false);
     onUnloadRegistry.push(onUnloadPermission);
     permTab.hidden = false;
--- a/browser/base/content/test/general/browser_bug592338.js
+++ b/browser/base/content/test/general/browser_bug592338.js
@@ -43,17 +43,17 @@ function test_install_http() {
     });
   }, false);
 },
 
 function test_install_lwtheme() {
   is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
 
   var pm = Services.perms;
-  pm.add(makeURI("https://example.com/"), "install", pm.ALLOW_ACTION);
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   gBrowser.selectedTab = gBrowser.addTab("https://example.com/browser/browser/base/content/test/general/bug592338.html");
   gBrowser.selectedBrowser.addEventListener("pageshow", function() {
     if (gBrowser.contentDocument.location.href == "about:blank")
       return;
 
     gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee, false);
 
--- a/browser/base/content/test/plugins/head.js
+++ b/browser/base/content/test/plugins/head.js
@@ -233,17 +233,17 @@ function promiseReloadPlugin(aId, aBrows
 
 // after a test is done using the plugin doorhanger, we should just clear
 // any permissions that may have crept in
 function clearAllPluginPermissions() {
   let perms = Services.perms.enumerator;
   while (perms.hasMoreElements()) {
     let perm = perms.getNext();
     if (perm.type.startsWith('plugin')) {
-      info("removing permission:" + perm.principal.origin + " " + perm.type + "\n");
+      info("removing permission:" + perm.host + " " + perm.type + "\n");
       Services.perms.removePermission(perm);
     }
   }
 }
 
 function updateBlocklist(aCallback) {
   let blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"]
                           .getService(Ci.nsITimerCallback);
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -2427,33 +2427,30 @@ file, You can obtain one at http://mozil
       <method name="disableTrackingContentProtection">
         <body><![CDATA[
           // convert document URI into the format used by
           // nsChannelClassifier::ShouldEnableTrackingProtection
           // (any scheme turned into https is correct)
           let normalizedUrl = Services.io.newURI(
             "https://" + gBrowser.selectedBrowser.currentURI.hostPort,
             null, null);
-          // Add the current host/port combination in the 'trackingprotection' consumer of
+          // Add the current host in the 'trackingprotection' consumer of
           // the permission manager using a normalized URI. This effectively
-          // places this host/port combination on the tracking protection allowlist.
+          // places this host on the tracking protection allowlist.
           Services.perms.add(normalizedUrl,
             "trackingprotection", Services.perms.ALLOW_ACTION);
           BrowserReload();
         ]]></body>
       </method>
       <method name="enableTrackingContentProtection">
         <body><![CDATA[
-          // Remove the current host/port combination from the 'trackingprotection' consumer
-          // of the permission manager. This effectively removes this host/port combination
+          // Remove the current host from the 'trackingprotection' consumer
+          // of the permission manager. This effectively removes this host
           // from the tracking protection allowlist.
-          let normalizedUrl = Services.io.newURI(
-            "https://" + gBrowser.selectedBrowser.currentURI.hostPort,
-            null, null);
-          Services.perms.remove(normalizedUrl,
+          Services.perms.remove(gBrowser.selectedBrowser.currentURI,
             "trackingprotection");
           BrowserReload();
         ]]></body>
       </method>
     </implementation>
   </binding>
 
   <binding id="click-to-play-plugins-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
@@ -2559,18 +2556,18 @@ file, You can obtain one at http://mozil
           var grid = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-center-box");
 
           if (this._states.SINGLE == state) {
             grid.hidden = true;
             this._setupSingleState();
             return;
           }
 
-          let prePath = this.notification.options.principal.URI.prePath;
-          this._setupDescription("pluginActivateMultiple.message", null, prePath);
+          let host = this.notification.options.host;
+          this._setupDescription("pluginActivateMultiple.message", null, host);
 
           var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox");
 
           var dialogStrings = Services.strings.createBundle("chrome://global/locale/dialog.properties");
           this._primaryButton.label = dialogStrings.GetStringFromName("button-accept");
           this._primaryButton.setAttribute("default", "true");
 
           this._secondaryButton.label = dialogStrings.GetStringFromName("button-cancel");
@@ -2599,17 +2596,17 @@ file, You can obtain one at http://mozil
             showBox.hidden = true;
           }
           this._setupLink(null);
         ]]></body>
       </method>
       <method name="_setupSingleState">
         <body><![CDATA[
           var action = this._items[0].action;
-          var prePath = action.pluginPermissionPrePath;
+          var host = action.pluginPermissionHost;
 
           let label, linkLabel, linkUrl, button1, button2;
 
           if (action.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
             button1 = {
               label: "pluginBlockNow.label",
               accesskey: "pluginBlockNow.accesskey",
               action: "_singleBlock"
@@ -2694,17 +2691,17 @@ file, You can obtain one at http://mozil
               linkLabel = "pluginActivate.riskLabel"
               button1.default = true;
               break;
 
             default:
               Cu.reportError(Error("Unexpected blocklist state"));
             }
           }
-          this._setupDescription(label, action.pluginName, prePath);
+          this._setupDescription(label, action.pluginName, host);
           this._setupLink(linkLabel, action.detailsLink);
 
           this._primaryButton.label = gNavigatorBundle.getString(button1.label);
           this._primaryButton.accessKey = gNavigatorBundle.getString(button1.accesskey);
           this._primaryButton.setAttribute("action", button1.action);
 
           this._secondaryButton.label = gNavigatorBundle.getString(button2.label);
           this._secondaryButton.accessKey = gNavigatorBundle.getString(button2.accesskey);
@@ -2715,35 +2712,35 @@ file, You can obtain one at http://mozil
           else if (button2.default) {
             this._secondaryButton.setAttribute("default", "true");
           }
         ]]></body>
       </method>
       <method name="_setupDescription">
         <parameter name="baseString" />
         <parameter name="pluginName" /> <!-- null for the multiple-plugin case -->
-        <parameter name="prePath" />
+        <parameter name="host" />
         <body><![CDATA[
           var bsn = this._brandShortName;
           var span = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description");
           while (span.lastChild) {
             span.removeChild(span.lastChild);
           }
 
-          var args = ["__prepath__", this._brandShortName];
+          var args = ["__host__", this._brandShortName];
           if (pluginName) {
             args.unshift(pluginName);
           }
           var bases = gNavigatorBundle.getFormattedString(baseString, args).
-            split("__prepath__", 2);
+            split("__host__", 2);
 
           span.appendChild(document.createTextNode(bases[0]));
-          var prePathSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em");
-          prePathSpan.appendChild(document.createTextNode(prePath));
-          span.appendChild(prePathSpan);
+          var hostSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em");
+          hostSpan.appendChild(document.createTextNode(host));
+          span.appendChild(hostSpan);
           span.appendChild(document.createTextNode(bases[1] + " "));
         ]]></body>
       </method>
       <method name="_setupLink">
         <parameter name="linkString"/>
         <parameter name="linkUrl" />
         <body><![CDATA[
           var link = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-link");
--- a/browser/components/preferences/aboutPermissions.js
+++ b/browser/components/preferences/aboutPermissions.js
@@ -12,29 +12,26 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/DownloadUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/ForgetAboutSite.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
                                   "resource://gre/modules/PluralForm.jsm");
 
-let gSecMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
-              getService(Ci.nsIScriptSecurityManager);
-
 let gFaviconService = Cc["@mozilla.org/browser/favicon-service;1"].
                       getService(Ci.nsIFaviconService);
 
 let gPlacesDatabase = Cc["@mozilla.org/browser/nav-history-service;1"].
                       getService(Ci.nsPIPlacesDatabase).
                       DBConnection.
                       clone(true);
 
 let gSitesStmt = gPlacesDatabase.createAsyncStatement(
-                  "SELECT url " +
+                  "SELECT get_unreversed_host(rev_host) AS host " +
                   "FROM moz_places " +
                   "WHERE rev_host > '.' " +
                   "AND visit_count > 0 " +
                   "GROUP BY rev_host " +
                   "ORDER BY MAX(frecency) DESC " +
                   "LIMIT :limit");
 
 let gVisitStmt = gPlacesDatabase.createAsyncStatement(
@@ -44,21 +41,24 @@ let gVisitStmt = gPlacesDatabase.createA
 
 /**
  * Permission types that should be tested with testExactPermission, as opposed
  * to testPermission. This is based on what consumers use to test these permissions.
  */
 let TEST_EXACT_PERM_TYPES = ["geo", "camera", "microphone"];
 
 /**
- * Site object represents a single site, uniquely identified by a principal.
+ * Site object represents a single site, uniquely identified by a host.
  */
-function Site(principal) {
-  this.principal = principal;
+function Site(host) {
+  this.host = host;
   this.listitem = null;
+
+  this.httpURI = NetUtil.newURI("http://" + this.host);
+  this.httpsURI = NetUtil.newURI("https://" + this.host);
 }
 
 Site.prototype = {
   /**
    * Gets the favicon to use for the site. The callback only gets called if
    * a favicon is found for either the http URI or the https URI.
    *
    * @param aCallback
@@ -70,34 +70,38 @@ Site.prototype = {
         // Use getFaviconLinkForIcon to get image data from the database instead
         // of using the favicon URI to fetch image data over the network.
         aCallback(gFaviconService.getFaviconLinkForIcon(aFaviconURI).spec);
       } catch (e) {
         Cu.reportError("AboutPermissions: " + e);
       }
     }
 
-    // Get the favicon for the origin
-    gFaviconService.getFaviconURLForPage(this.principal.URI, function (aURI) {
+    // Try to find favicon for both URIs, but always prefer the https favicon.
+    gFaviconService.getFaviconURLForPage(this.httpsURI, function (aURI) {
       if (aURI) {
         invokeCallback(aURI);
+      } else {
+        gFaviconService.getFaviconURLForPage(this.httpURI, function (aURI) {
+          if (aURI) {
+            invokeCallback(aURI);
+          }
+        });
       }
     }.bind(this));
   },
 
   /**
    * Gets the number of history visits for the site.
    *
    * @param aCallback
    *        A function that takes the visit count (a number) as a parameter.
    */
   getVisitCount: function Site_getVisitCount(aCallback) {
-    // XXX This won't be a very reliable system, as it will count both http: and https: visits
-    // Unfortunately, I don't think that there is a much better way to do it right now.
-    let rev_host = this.principal.URI.host.split("").reverse().join("") + ".";
+    let rev_host = this.host.split("").reverse().join("") + ".";
     gVisitStmt.params.rev_host = rev_host;
     gVisitStmt.executeAsync({
       handleResult: function(aResults) {
         let row = aResults.getNextRow();
         let count = row.getResultByName("count") || 0;
         try {
           aCallback(count);
         } catch (e) {
@@ -130,19 +134,19 @@ Site.prototype = {
       aResultObj.value =  this.loginSavingEnabled ?
                           Ci.nsIPermissionManager.ALLOW_ACTION :
                           Ci.nsIPermissionManager.DENY_ACTION;
       return true;
     }
 
     let permissionValue;
     if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) {
-      permissionValue = Services.perms.testPermissionFromPrincipal(this.principal, aType);
+      permissionValue = Services.perms.testPermission(this.httpURI, aType);
     } else {
-      permissionValue = Services.perms.testExactPermissionFromPrincipal(this.principal, aType);
+      permissionValue = Services.perms.testExactPermission(this.httpURI, aType);
     }
     aResultObj.value = permissionValue;
 
     return permissionValue != Ci.nsIPermissionManager.UNKNOWN_ACTION;
   },
 
   /**
    * Sets a permission for the site given a permission type and value.
@@ -157,45 +161,46 @@ Site.prototype = {
   setPermission: function Site_setPermission(aType, aPerm) {
     // Password saving isn't a nsIPermissionManager permission type, so handle
     // it seperately.
     if (aType == "password") {
       this.loginSavingEnabled = aPerm == Ci.nsIPermissionManager.ALLOW_ACTION;
       return;
     }
 
-    Services.perms.addFromPrincipal(this.principal, aType, aPerm);
+    // Using httpURI is kind of bogus, but the permission manager stores the
+    // permission for the host, so the right thing happens in the end.
+    Services.perms.add(this.httpURI, aType, aPerm);
   },
 
   /**
    * Clears a user-set permission value for the site given a permission type.
    *
    * @param aType
    *        The permission type string stored in permission manager.
    *        e.g. "cookie", "geo", "indexedDB", "popup", "image"
    */
   clearPermission: function Site_clearPermission(aType) {
-    Services.perms.removeFromPrincipal(this.principal, aType);
+    Services.perms.remove(this.httpURI, aType);
   },
 
   /**
    * Gets cookies stored for the site. This does not return cookies stored
    * for the base domain, only the exact hostname stored for the site.
    *
    * @return An array of the cookies set for the site.
    */
   get cookies() {
-    let host = this.principal.URI.host;
     let cookies = [];
-    let enumerator = Services.cookies.getCookiesFromHost(host);
+    let enumerator = Services.cookies.getCookiesFromHost(this.host);
     while (enumerator.hasMoreElements()) {
       let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
       // getCookiesFromHost returns cookies for base domain, but we only want
       // the cookies for the exact domain.
-      if (cookie.rawHost == host) {
+      if (cookie.rawHost == this.host) {
         cookies.push(cookie);
       }
     }
     return cookies;
   },
 
   /**
    * Removes a set of specific cookies from the browser.
@@ -207,37 +212,37 @@ Site.prototype = {
   },
 
   /**
    * Gets logins stored for the site.
    *
    * @return An array of the logins stored for the site.
    */
   get logins() {
-    let logins = Services.logins.findLogins({}, this.principal.originNoSuffix, "", "");
-    return logins;
+    let httpLogins = Services.logins.findLogins({}, this.httpURI.prePath, "", "");
+    let httpsLogins = Services.logins.findLogins({}, this.httpsURI.prePath, "", "");
+    return httpLogins.concat(httpsLogins);
   },
 
   get loginSavingEnabled() {
-    return Services.logins.getLoginSavingEnabled(this.principal.originNoSuffix);
+    // Only say that login saving is blocked if it is blocked for both http and https.
+    return Services.logins.getLoginSavingEnabled(this.httpURI.prePath) &&
+           Services.logins.getLoginSavingEnabled(this.httpsURI.prePath);
   },
 
   set loginSavingEnabled(isEnabled) {
-    Services.logins.setLoginSavingEnabled(this.principal.originNoSuffix, isEnabled);
+    Services.logins.setLoginSavingEnabled(this.httpURI.prePath, isEnabled);
+    Services.logins.setLoginSavingEnabled(this.httpsURI.prePath, isEnabled);
   },
 
   /**
    * Removes all data from the browser corresponding to the site.
    */
   forgetSite: function Site_forgetSite() {
-    // XXX This removes data for an entire domain, rather than just
-    // an origin. This may produce confusing results, as data will
-    // be cleared for the http:// as well as the https:// domain
-    // if you try to forget the https:// site.
-    ForgetAboutSite.removeDataFromDomain(this.principal.URI.host);
+    ForgetAboutSite.removeDataFromDomain(this.host);
   }
 }
 
 /**
  * PermissionDefaults object keeps track of default permissions for sites based
  * on global preferences.
  *
  * Inspired by pageinfo/permissions.js
@@ -356,17 +361,17 @@ let AboutPermissions = {
 
   /**
    * When adding sites to the dom sites-list, divide workload into intervals.
    */
   LIST_BUILD_CHUNK: 5, // interval size
   LIST_BUILD_DELAY: 100, // delay between intervals
 
   /**
-   * Stores a mapping of origin strings to Site objects.
+   * Stores a mapping of host strings to Site objects.
    */
   _sites: {},
 
   sitesList: null,
   _selectedSite: null,
 
   /**
    * For testing, track initializations so we can send notifications
@@ -462,19 +467,19 @@ let AboutPermissions = {
         // aSubject is null when nsIPermisionManager::removeAll() is called.
         if (!aSubject) {
           this._supportedPermissions.forEach(function(aType){
             this.updatePermission(aType);
           }, this);
           break;
         }
         let permission = aSubject.QueryInterface(Ci.nsIPermission);
-        // We can't compare selectedSite.principal and permission.principal here
-        // because we need to handle the case where a parent domain was changed
-        // in a way that affects the subdomain.
+        // We can't compare selectedSite.host and permission.host here because
+        // we need to handle the case where a parent domain was changed in a
+        // way that affects the subdomain.
         if (this._supportedPermissions.indexOf(permission.type) != -1) {
           this.updatePermission(permission.type);
         }
         break;
       case "nsPref:changed":
         this._supportedPermissions.forEach(function(aType){
           this.updatePermission(aType);
         }, this);
@@ -502,21 +507,18 @@ let AboutPermissions = {
    */
   getSitesFromPlaces: function() {
     gSitesStmt.params.limit = this.PLACES_SITES_LIMIT;
     gSitesStmt.executeAsync({
       handleResult: function(aResults) {
         AboutPermissions.startSitesListBatch();
         let row;
         while (row = aResults.getNextRow()) {
-          let spec = row.getResultByName("url");
-          let uri = NetUtil.newURI(spec);
-          let principal = gSecMan.getNoAppCodebasePrincipal(uri);
-
-          AboutPermissions.addPrincipal(principal);
+          let host = row.getResultByName("host");
+          AboutPermissions.addHost(host);
         }
         AboutPermissions.endSitesListBatch();
       },
       handleError: function(aError) {
         Cu.reportError("AboutPermissions: " + aError);
       },
       handleCompletion: function(aReason) {
         // Notify oberservers for testing purposes.
@@ -555,90 +557,88 @@ let AboutPermissions = {
     let logins = Services.logins.getAllLogins();
     logins.forEach(function(aLogin) {
       if (itemCnt % this.LIST_BUILD_CHUNK == 0) {
         yield true;
       }
       try {
         // aLogin.hostname is a string in origin URL format (e.g. "http://foo.com")
         let uri = NetUtil.newURI(aLogin.hostname);
-        let principal = gSecMan.getNoAppCodebasePrincipal(uri);
-        this.addPrincipal(principal);
+        this.addHost(uri.host);
       } catch (e) {
         // newURI will throw for add-ons logins stored in chrome:// URIs
       }
       itemCnt++;
     }, this);
 
     let disabledHosts = Services.logins.getAllDisabledHosts();
     disabledHosts.forEach(function(aHostname) {
       if (itemCnt % this.LIST_BUILD_CHUNK == 0) {
         yield true;
       }
       try {
         // aHostname is a string in origin URL format (e.g. "http://foo.com")
         let uri = NetUtil.newURI(aHostname);
-        let principal = gSecMan.getNoAppCodebasePrincipal(uri);
-        this.addPrincipal(principal);
+        this.addHost(uri.host);
       } catch (e) {
         // newURI will throw for add-ons logins stored in chrome:// URIs
       }
       itemCnt++;
     }, this);
 
     let enumerator = Services.perms.enumerator;
     while (enumerator.hasMoreElements()) {
       if (itemCnt % this.LIST_BUILD_CHUNK == 0) {
         yield true;
       }
       let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
       // Only include sites with exceptions set for supported permission types.
       if (this._supportedPermissions.indexOf(permission.type) != -1) {
-        this.addPrincipal(permission.principal);
+        this.addHost(permission.host);
       }
       itemCnt++;
     }
 
     yield false;
   },
 
   /**
    * Creates a new Site and adds it to _sites if it's not already there.
    *
-   * @param aPrincipal
-   *        A principal.
+   * @param aHost
+   *        A host string.
    */
-  addPrincipal: function(aPrincipal) {
-    if (aPrincipal.origin in this._sites) {
+  addHost: function(aHost) {
+    if (aHost in this._sites) {
       return;
     }
-    let site = new Site(aPrincipal);
-    this._sites[aPrincipal.origin] = site;
+    let site = new Site(aHost);
+    this._sites[aHost] = site;
     this.addToSitesList(site);
   },
 
   /**
    * Populates sites-list richlistbox with data from Site object.
    *
    * @param aSite
    *        A Site object.
    */
   addToSitesList: function(aSite) {
     let item = document.createElement("richlistitem");
     item.setAttribute("class", "site");
-    item.setAttribute("value", aSite.principal.origin);
+    item.setAttribute("value", aSite.host);
 
     aSite.getFavicon(function(aURL) {
       item.setAttribute("favicon", aURL);
     });
     aSite.listitem = item;
 
     // Make sure to only display relevant items when list is filtered
     let filterValue = document.getElementById("sites-filter").value.toLowerCase();
-    item.collapsed = aSite.principal.origin.toLowerCase().indexOf(filterValue) == -1;
+    item.collapsed = aSite.host.toLowerCase().indexOf(filterValue) == -1;
 
     (this._listFragment || this.sitesList).appendChild(item);
   },
 
   startSitesListBatch: function () {
     if (!this._listFragment)
       this._listFragment = document.createDocumentFragment();
   },
@@ -681,44 +681,44 @@ let AboutPermissions = {
   /**
    * Deletes sites for a host and all of its sub-domains. Removes these sites
    * from _sites and removes their corresponding elements from the DOM.
    *
    * @param aHost
    *        The host string corresponding to the site to delete.
    */
   deleteFromSitesList: function(aHost) {
-    for (let origin in this._sites) {
-      let site = this._sites[origin];
-      if (site.principal.URI.host.hasRootDomain(aHost)) {
+    for (let host in this._sites) {
+      let site = this._sites[host];
+      if (site.host.hasRootDomain(aHost)) {
         if (site == this._selectedSite) {
           // Replace site-specific interface with "All Sites" interface.
           this.sitesList.selectedItem = document.getElementById("all-sites-item");
         }
 
         this.sitesList.removeChild(site.listitem);
-        delete this._sites[site.principal.origin];
+        delete this._sites[site.host];
       }
     }
   },
 
   /**
    * Shows interface for managing site-specific permissions.
    */
   onSitesListSelect: function(event) {
     if (event.target.selectedItem.id == "all-sites-item") {
       // Clear the header label value from the previously selected site.
       document.getElementById("site-label").value = "";
       this.manageDefaultPermissions();
       return;
     }
 
-    let origin = event.target.value;
-    let site = this._selectedSite = this._sites[origin];
-    document.getElementById("site-label").value = origin;
+    let host = event.target.value;
+    let site = this._selectedSite = this._sites[host];
+    document.getElementById("site-label").value = host;
     document.getElementById("header-deck").selectedPanel =
       document.getElementById("site-header");
 
     this.updateVisitCount();
     this.updatePermissionsBox();
   },
 
   /**
@@ -763,19 +763,19 @@ let AboutPermissions = {
                       this._noGlobalDeny.indexOf(aType) != -1;
 
     let permissionMenulist = document.getElementById(aType + "-menulist");
     let permissionValue;
     if (!this._selectedSite) {
       // If there is no selected site, we are updating the default permissions interface.
       permissionValue = PermissionDefaults[aType];
       if (aType == "cookie")
-	      // cookie-9 corresponds to ALLOW_FIRST_PARTY_ONLY, which is reserved
-	      // for site-specific preferences only.
-	      document.getElementById("cookie-9").hidden = true;
+	// cookie-9 corresponds to ALLOW_FIRST_PARTY_ONLY, which is reserved
+	// for site-specific preferences only.
+	document.getElementById("cookie-9").hidden = true;
     } else {
       if (aType == "cookie")
         document.getElementById("cookie-9").hidden = false;
       let result = {};
       permissionValue = this._selectedSite.getPermission(aType, result) ?
                         result.value : PermissionDefaults[aType];
     }
 
@@ -820,28 +820,28 @@ let AboutPermissions = {
     document.getElementById("passwords-manage-all-button").hidden = true;
     document.getElementById("passwords-count").hidden = false;
   },
 
   /**
    * Opens password manager dialog.
    */
   managePasswords: function() {
-    let selectedOrigin = "";
+    let selectedHost = "";
     if (this._selectedSite) {
-      selectedOrigin = this._selectedSite.principal.URI.prePath;
+      selectedHost = this._selectedSite.host;
     }
 
     let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager");
     if (win) {
-      win.setFilter(selectedOrigin);
+      win.setFilter(selectedHost);
       win.focus();
     } else {
       window.openDialog("chrome://passwordmgr/content/passwordManager.xul",
-                        "Toolkit:PasswordManager", "", {filterString : selectedOrigin});
+                        "Toolkit:PasswordManager", "", {filterString : selectedHost});
     }
   },
 
   updateCookiesCount: function() {
     if (!this._selectedSite) {
       document.getElementById("cookies-count").hidden = true;
       document.getElementById("cookies-clear-all-button").hidden = false;
       document.getElementById("cookies-manage-all-button").hidden = false;
@@ -872,21 +872,19 @@ let AboutPermissions = {
     site.clearCookies(site.cookies);
     this.updateCookiesCount();
   },
 
   /**
    * Opens cookie manager dialog.
    */
   manageCookies: function() {
-    // Cookies are stored by-host, and thus we filter the cookie window
-    // using only the host of the selected principal's origin
     let selectedHost = "";
     if (this._selectedSite) {
-      selectedHost = this._selectedSite.principal.URI.host;
+      selectedHost = this._selectedSite.host;
     }
 
     let win = Services.wm.getMostRecentWindow("Browser:Cookies");
     if (win) {
       win.gCookiesWindow.setFilter(selectedHost);
       win.focus();
     } else {
       window.openDialog("chrome://browser/content/preferences/cookies.xul",
--- a/browser/components/preferences/advanced.js
+++ b/browser/components/preferences/advanced.js
@@ -4,17 +4,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 // Load DownloadUtils module for convertByteUnits
 Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
 Components.utils.import("resource://gre/modules/ctypes.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
 
 var gAdvancedPane = {
   _inited: false,
 
   /**
    * Brings the appropriate tab to the front and initializes various bits of UI.
    */
   init: function ()
@@ -467,17 +466,17 @@ var gAdvancedPane = {
       groups = cacheService.getGroups();
 
     var ios = Components.classes["@mozilla.org/network/io-service;1"].
               getService(Components.interfaces.nsIIOService);
 
     var usage = 0;
     for (var i = 0; i < groups.length; i++) {
       var uri = ios.newURI(groups[i], null, null);
-      if (perm.matchesURI(uri, true)) {
+      if (uri.asciiHost == perm.host) {
         var cache = cacheService.getActiveCache(groups[i]);
         usage += cache.usage;
       }
     }
 
     return usage;
   },
 
@@ -504,17 +503,17 @@ var gAdvancedPane = {
     while (enumerator.hasMoreElements()) {
       var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
       if (perm.type == "offline-app" &&
           perm.capability != Components.interfaces.nsIPermissionManager.DEFAULT_ACTION &&
           perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) {
         var row = document.createElement("listitem");
         row.id = "";
         row.className = "offlineapp";
-        row.setAttribute("origin", perm.principal.origin);
+        row.setAttribute("host", perm.host);
         var converted = DownloadUtils.
                         convertByteUnits(this._getOfflineAppUsage(perm, groups));
         row.setAttribute("usage",
                          bundle.getFormattedString("offlineAppUsage",
                                                    converted));
         list.appendChild(row);
       }
     }
@@ -530,53 +529,58 @@ var gAdvancedPane = {
       removeButton.setAttribute("disabled", "true");
     }
   },
 
   removeOfflineApp: function()
   {
     var list = document.getElementById("offlineAppsList");
     var item = list.selectedItem;
-    var origin = item.getAttribute("origin");
-    var principal = BrowserUtils.principalFromOrigin(origin);
+    var host = item.getAttribute("host");
 
     var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                             .getService(Components.interfaces.nsIPromptService);
     var flags = prompts.BUTTON_TITLE_IS_STRING * prompts.BUTTON_POS_0 +
                 prompts.BUTTON_TITLE_CANCEL * prompts.BUTTON_POS_1;
 
     var bundle = document.getElementById("bundlePreferences");
     var title = bundle.getString("offlineAppRemoveTitle");
-    var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [principal.URI.prePath]);
+    var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [host]);
     var confirm = bundle.getString("offlineAppRemoveConfirm");
     var result = prompts.confirmEx(window, title, prompt, flags, confirm,
                                    null, null, null, {});
     if (result != 0)
       return;
 
-    // get the permission
-    var pm = Components.classes["@mozilla.org/permissionmanager;1"]
-                       .getService(Components.interfaces.nsIPermissionManager);
-    var perm = pm.getPermissionObject(principal, "offline-app");
-
     // clear offline cache entries
     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
                        getService(Components.interfaces.nsIApplicationCacheService);
     var ios = Components.classes["@mozilla.org/network/io-service;1"].
               getService(Components.interfaces.nsIIOService);
     var groups = cacheService.getGroups();
     for (var i = 0; i < groups.length; i++) {
-        var uri = ios.newURI(groups[i], null, null);
-        if (perm.matchesURI(uri, true)) {
+        let uri = ios.newURI(groups[i], null, null);
+        if (uri.asciiHost == host) {
             var cache = cacheService.getActiveCache(groups[i]);
             cache.discard();
         }
     }
 
-    pm.removePermission(perm);
+    // remove the permission
+    var pm = Components.classes["@mozilla.org/permissionmanager;1"]
+                       .getService(Components.interfaces.nsIPermissionManager);
+    let uri;
+    try {
+      // file:// URIs are stored with their scheme. We try to parse them first, as
+      // URIs like http://file:///foo/bar/baz.html will parse as HTTP URIs.
+      uri = ios.newURI(host, null, null);
+    } catch (e) {
+      uri = ios.newURI("http://" + host, null, null);
+    }
+    pm.remove(uri, "offline-app");
 
     list.removeChild(item);
     gAdvancedPane.offlineAppSelected();
     this.updateActualAppCacheSize();
   },
 
   // UPDATE TAB
 
--- a/browser/components/preferences/in-content/advanced.js
+++ b/browser/components/preferences/in-content/advanced.js
@@ -497,17 +497,17 @@ var gAdvancedPane = {
     var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
                        getService(Components.interfaces.nsIApplicationCacheService);
     var ios = Components.classes["@mozilla.org/network/io-service;1"].
               getService(Components.interfaces.nsIIOService);
 
     var usage = 0;
     for (var i = 0; i < groups.length; i++) {
       var uri = ios.newURI(groups[i], null, null);
-      if (perm.matchesURI(uri, true)) {
+      if (uri.asciiHost == perm.host) {
         var cache = cacheService.getActiveCache(groups[i]);
         usage += cache.usage;
       }
     }
 
     return usage;
   },
 
@@ -539,17 +539,17 @@ var gAdvancedPane = {
     while (enumerator.hasMoreElements()) {
       var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
       if (perm.type == "offline-app" &&
           perm.capability != Components.interfaces.nsIPermissionManager.DEFAULT_ACTION &&
           perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) {
         var row = document.createElement("listitem");
         row.id = "";
         row.className = "offlineapp";
-        row.setAttribute("origin", perm.principal.origin);
+        row.setAttribute("host", perm.host);
         var converted = DownloadUtils.
                         convertByteUnits(this._getOfflineAppUsage(perm, groups));
         row.setAttribute("usage",
                          bundle.getFormattedString("offlineAppUsage",
                                                    converted));
         list.appendChild(row);
       }
     }
@@ -565,55 +565,60 @@ var gAdvancedPane = {
       removeButton.setAttribute("disabled", "true");
     }
   },
 
   removeOfflineApp: function()
   {
     var list = document.getElementById("offlineAppsList");
     var item = list.selectedItem;
-    var origin = item.getAttribute("origin");
-    var principal = BrowserUtils.principalFromOrigin(origin);
+    var host = item.getAttribute("host");
 
     var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                             .getService(Components.interfaces.nsIPromptService);
     var flags = prompts.BUTTON_TITLE_IS_STRING * prompts.BUTTON_POS_0 +
                 prompts.BUTTON_TITLE_CANCEL * prompts.BUTTON_POS_1;
 
     var bundle = document.getElementById("bundlePreferences");
     var title = bundle.getString("offlineAppRemoveTitle");
-    var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [principal.URI.prePath]);
+    var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [host]);
     var confirm = bundle.getString("offlineAppRemoveConfirm");
     var result = prompts.confirmEx(window, title, prompt, flags, confirm,
                                    null, null, null, {});
     if (result != 0)
       return;
 
-    // get the permission
-    var pm = Components.classes["@mozilla.org/permissionmanager;1"]
-                       .getService(Components.interfaces.nsIPermissionManager);
-    var perm = pm.getPermissionObject(principal, "offline-app");
-
     // clear offline cache entries
     try {
       var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
                          getService(Components.interfaces.nsIApplicationCacheService);
       var ios = Components.classes["@mozilla.org/network/io-service;1"].
                 getService(Components.interfaces.nsIIOService);
       var groups = cacheService.getGroups();
       for (var i = 0; i < groups.length; i++) {
-          var uri = ios.newURI(groups[i], null, null);
-          if (perm.matchesURI(uri, true)) {
+          let uri = ios.newURI(groups[i], null, null);
+          if (uri.asciiHost == host) {
               var cache = cacheService.getActiveCache(groups[i]);
               cache.discard();
           }
       }
     } catch (e) {}
 
-    pm.removePermission(perm);
+    // remove the permission
+    var pm = Components.classes["@mozilla.org/permissionmanager;1"]
+                       .getService(Components.interfaces.nsIPermissionManager);
+    let uri;
+    try {
+      // file:// URIs are stored with their scheme. We try to parse them first, as
+      // URIs like http://file:///foo/bar/baz.html will parse as HTTP URIs.
+      uri = ios.newURI(host, null, null);
+    } catch (e) {
+      uri = ios.newURI("http://" + host, null, null);
+    }
+    pm.remove(uri, "offline-app");
 
     list.removeChild(item);
     gAdvancedPane.offlineAppSelected();
     this.updateActualAppCacheSize();
   },
 
   // UPDATE TAB
 
--- a/browser/components/preferences/permissions.js
+++ b/browser/components/preferences/permissions.js
@@ -4,20 +4,20 @@
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
 const nsICookiePermission = Components.interfaces.nsICookiePermission;
 
 const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions";
 
-function Permission(principal, type, capability)
+function Permission(host, rawHost, type, capability)
 {
-  this.principal = principal;
-  this.origin = principal.origin;
+  this.host = host;
+  this.rawHost = rawHost;
   this.type = type;
   this.capability = capability;
 }
 
 var gPermissionManager = {
   _type                 : "",
   _permissions          : [],
   _permissionsToAdd     : new Map(),
@@ -30,17 +30,17 @@ var gPermissionManager = {
     _rowCount: 0,
     get rowCount()
     {
       return this._rowCount;
     },
     getCellText: function (aRow, aColumn)
     {
       if (aColumn.id == "siteCol")
-        return gPermissionManager._permissions[aRow].origin;
+        return gPermissionManager._permissions[aRow].rawHost;
       else if (aColumn.id == "statusCol")
         return gPermissionManager._permissions[aRow].capability;
       return "";
     },
 
     isSeparator: function(aIndex) { return false; },
     isSorted: function() { return false; },
     isContainer: function(aIndex) { return false; },
@@ -77,81 +77,74 @@ var gPermissionManager = {
       break;
     }
     return this._bundle.getString(stringKey);
   },
 
   addPermission: function (aCapability)
   {
     var textbox = document.getElementById("url");
-    var input_url = textbox.value.replace(/^\s*/, ""); // trim any leading space
-    let principal;
+    var host = textbox.value.replace(/^\s*([-\w]*:\/+)?/, ""); // trim any leading space and scheme
     try {
-      // If the uri doesn't successfully parse, try adding a http:// and parsing again
-      let uri;
-      try {
-        let uri = Services.io.newURI(input_url, null, null);
-      } catch(ex) {
-        uri = Services.io.newURI("http://" + input_url, null, null);
-      }
-      principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
+      var uri = Services.io.newURI("http://"+host, null, null);
+      host = uri.host;
     } catch(ex) {
       var message = this._bundle.getString("invalidURI");
       var title = this._bundle.getString("invalidURITitle");
       Services.prompt.alert(window, title, message);
       return;
     }
 
     var capabilityString = this._getCapabilityString(aCapability);
 
     // check whether the permission already exists, if not, add it
-    let permissionExists = false;
+    let hostExists = false;
     let capabilityExists = false;
     for (var i = 0; i < this._permissions.length; ++i) {
-      if (this._permissions[i].principal.equals(principal)) {
-        permissionExists = true;
+      if (this._permissions[i].rawHost == host) {
+        hostExists = true;
         capabilityExists = this._permissions[i].capability == capabilityString;
         if (!capabilityExists) {
           this._permissions[i].capability = capabilityString;
         }
         break;
       }
     }
 
-    let permissionParams = {principal: principal, type: this._type, capability: aCapability};
-    if (!permissionExists) {
-      this._permissionsToAdd.set(principal.origin, permissionParams);
+    let permissionParams = {host: host, type: this._type, capability: aCapability};
+    if (!hostExists) {
+      this._permissionsToAdd.set(host, permissionParams);
       this._addPermission(permissionParams);
     }
     else if (!capabilityExists) {
-      this._permissionsToAdd.set(principal.origin, permissionParams);
-      this._handleCapabilityChange();
+        this._permissionsToAdd.set(host, permissionParams);
+        this._handleCapabilityChange();
     }
 
     textbox.value = "";
     textbox.focus();
 
     // covers a case where the site exists already, so the buttons don't disable
     this.onHostInput(textbox);
 
     // enable "remove all" button as needed
     document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0;
   },
 
   _removePermission: function(aPermission)
   {
-    this._removePermissionFromList(aPermission.principal);
+    this._removePermissionFromList(aPermission.host);
 
     // If this permission was added during this session, let's remove
     // it from the pending adds list to prevent calls to the
     // permission manager.
-    let isNewPermission = this._permissionsToAdd.delete(aPermission.principal.origin);
+    let isNewPermission = this._permissionsToAdd.delete(aPermission.host);
 
     if (!isNewPermission) {
-      this._permissionsToDelete.set(aPermission.principal.origin, aPermission);
+      this._permissionsToDelete.set(aPermission.host, aPermission);
     }
 
   },
 
   _handleCapabilityChange: function ()
   {
     // Re-do the sort, if the status changed from Block to Allow
     // or vice versa, since if we're sorted on status, we may no
@@ -278,17 +271,17 @@ var gPermissionManager = {
       if (permission.type != this._type)
         return;
 
       if (aData == "added") {
         this._addPermission(permission);
       }
       else if (aData == "changed") {
         for (var i = 0; i < this._permissions.length; ++i) {
-          if (permission.matches(this._permissions[i].principal, true)) {
+          if (this._permissions[i].host == permission.host) {
             this._permissions[i].capability = this._getCapabilityString(permission.capability);
             break;
           }
         }
         this._handleCapabilityChange();
       }
       else if (aData == "deleted") {
         this._removePermissionFromList(permission);
@@ -365,21 +358,23 @@ var gPermissionManager = {
   onApplyChanges: function()
   {
     // Stop observing permission changes since we are about
     // to write out the pending adds/deletes and don't need
     // to update the UI
     this.uninit();
 
     for (let permissionParams of this._permissionsToAdd.values()) {
-      Services.perms.addFromPrincipal(permissionParams.principal, permissionParams.type, permissionParams.capability);
+      let uri = Services.io.newURI("http://" + permissionParams.host, null, null);
+      Services.perms.add(uri, permissionParams.type, permissionParams.capability);
     }
 
     for (let p of this._permissionsToDelete.values()) {
-      Services.perms.removeFromPrincipal(p.principal, p.type);
+      let uri = Services.io.newURI("http://" + p.host, null, null);
+      Services.perms.remove(uri, p.type);
     }
 
     window.close();
   },
 
   _loadPermissions: function ()
   {
     this._tree = document.getElementById("permissionsTree");
@@ -392,57 +387,58 @@ var gPermissionManager = {
       var nextPermission = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
       this._addPermissionToList(nextPermission);
     }
 
     this._view._rowCount = this._permissions.length;
 
     // sort and display the table
     this._tree.view = this._view;
-    this.onPermissionSort("origin");
+    this.onPermissionSort("rawHost");
 
     // disable "remove all" button if there are none
     document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0;
   },
 
   _addPermissionToList: function (aPermission)
   {
     if (aPermission.type == this._type &&
         (!this._manageCapability ||
          (aPermission.capability == this._manageCapability))) {
 
-      var principal = aPermission.principal;
+      var host = aPermission.host;
       var capabilityString = this._getCapabilityString(aPermission.capability);
-      var p = new Permission(principal,
+      var p = new Permission(host,
+                             (host.charAt(0) == ".") ? host.substring(1,host.length) : host,
                              aPermission.type,
                              capabilityString);
       this._permissions.push(p);
     }
   },
 
-  _removePermissionFromList: function (aPrincipal)
+  _removePermissionFromList: function (aHost)
   {
     for (let i = 0; i < this._permissions.length; ++i) {
-      if (this._permissions[i].principal.equals(aPrincipal)) {
+      if (this._permissions[i].host == aHost) {
         this._permissions.splice(i, 1);
         this._view._rowCount--;
         this._tree.treeBoxObject.rowCountChanged(this._view.rowCount - 1, -1);
         this._tree.treeBoxObject.invalidate();
         break;
       }
     }
   },
 
-  setOrigin: function (aOrigin)
+  setHost: function (aHost)
   {
-    document.getElementById("url").value = aOrigin;
+    document.getElementById("url").value = aHost;
   }
 };
 
-function setOrigin(aOrigin)
+function setHost(aHost)
 {
-  gPermissionManager.setOrigin(aOrigin);
+  gPermissionManager.setHost(aHost);
 }
 
 function initWithParams(aParams)
 {
   gPermissionManager.init(aParams);
 }
--- a/browser/components/preferences/tests/browser_chunk_permissions.js
+++ b/browser/components/preferences/tests/browser_chunk_permissions.js
@@ -98,40 +98,40 @@ var tests = [
   {
     desc: "test filtering before sites-list is fully constructed.",
     preInit: function() {
       let sitesFilter = gBrowser.contentDocument.getElementById("sites-filter");
       sitesFilter.value = TEST_URI_2.host;
       sitesFilter.doCommand();
     },
     run: function() {
-      let testSite1 = getSiteItem(TEST_URI_1.prePath);
+      let testSite1 = getSiteItem(TEST_URI_1.host);
       ok(testSite1.collapsed, "test site 1 is collapsed after early filtering");
-      let testSite2 = getSiteItem(TEST_URI_2.prePath);
+      let testSite2 = getSiteItem(TEST_URI_2.host);
       ok(!testSite2.collapsed, "test site 2 is not collapsed after early filtering");
-      let testSite3 = getSiteItem(TEST_URI_3.prePath);
+      let testSite3 = getSiteItem(TEST_URI_3.host);
       ok(testSite3.collapsed, "test site 3 is collapsed after early filtering");
 
       runNextTest();
     }
   },
   {
     desc: "test removing from sites-list before it is fully constructed.",
     preInit: function() {
       ForgetAboutSite.removeDataFromDomain(TEST_URI_2.host);
     },
     run: function() {
-      let testSite1 = getSiteItem(TEST_URI_1.prePath);
+      let testSite1 = getSiteItem(TEST_URI_1.host);
       ok(testSite1, "test site 1 was not removed from sites list");
-      let testSite2 = getSiteItem(TEST_URI_2.prePath);
+      let testSite2 = getSiteItem(TEST_URI_2.host);
       ok(!testSite2, "test site 2 was pre-removed from sites list");
-      let testSite3 = getSiteItem(TEST_URI_3.prePath);
+      let testSite3 = getSiteItem(TEST_URI_3.host);
       ok(testSite3, "test site 3 was not removed from sites list");
 
       runNextTest();
     }
   }
 ];
 
-function getSiteItem(aPrePath) {
+function getSiteItem(aHost) {
   return gBrowser.contentDocument.
-                  querySelector(".site[value='" + aPrePath + "']");
+                  querySelector(".site[value='" + aHost + "']");
 }
--- a/browser/components/preferences/tests/browser_cookies_exceptions.js
+++ b/browser/components/preferences/tests/browser_cookies_exceptions.js
@@ -15,58 +15,58 @@ var testRunner = {
         test: function(params) {
           params.url.value = "test.com";
           params.btnAllow.doCommand();
           is(params.tree.view.rowCount, 1, "added exception shows up in treeview");
           is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
                                           "permission text should be set correctly");
           params.btnApplyChanges.doCommand();
         },
-        observances: [{ type: "cookie", origin: "http://test.com", data: "added",
+        observances: [{ type: "cookie", host: "test.com", data: "added",
                         capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
       },
       {
         test: function(params) {
           params.url.value = "test.com";
           params.btnBlock.doCommand();
           is(params.tree.view.getCellText(0, params.statusCol), params.denyText,
                                           "permission should change to deny in UI");
           params.btnApplyChanges.doCommand();
         },
-        observances: [{ type: "cookie", origin: "http://test.com", data: "changed",
+        observances: [{ type: "cookie", host: "test.com", data: "changed",
                         capability: Ci.nsIPermissionManager.DENY_ACTION  }],
       },
       {
         test: function(params) {
           params.url.value = "test.com";
           params.btnAllow.doCommand();
           is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
                                           "permission should revert back to allow");
           params.btnApplyChanges.doCommand();
         },
-        observances: [{ type: "cookie", origin: "http://test.com", data: "changed",
+        observances: [{ type: "cookie", host: "test.com", data: "changed",
                         capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
       },
       {
         test: function(params) {
           params.url.value = "test.com";
           params.btnRemove.doCommand();
           is(params.tree.view.rowCount, 0, "exception should be removed");
           params.btnApplyChanges.doCommand();
         },
-        observances: [{ type: "cookie", origin: "http://test.com", data: "deleted" }],
+        observances: [{ type: "cookie", host: "test.com", data: "deleted" }],
       },
       {
         test: function(params) {
           let uri = params.ioService.newURI("http://test.com", null, null);
           params.pm.add(uri, "popup", Ci.nsIPermissionManager.DENY_ACTION);
           is(params.tree.view.rowCount, 0, "adding unrelated permission should not change display");
           params.btnApplyChanges.doCommand();
         },
-        observances: [{ type: "popup", origin: "http://test.com", data: "added",
+        observances: [{ type: "popup", host: "test.com", data: "added",
                         capability: Ci.nsIPermissionManager.DENY_ACTION }],
         cleanUp: function(params) {
           let uri = params.ioService.newURI("http://test.com", null, null);
           params.pm.remove(uri, "popup");
         },
       },
     ],
 
@@ -155,27 +155,22 @@ var testRunner = {
                 // See bug 1063410.
                 return;
               }
 
               let permission = aSubject.QueryInterface(Ci.nsIPermission);
               let expected = testRunner.tests[testRunner._currentTest].observances.shift();
 
               is(aData, expected.data, "type of message should be the same");
-              for each (let prop in ["type", "capability"]) {
+              for each (let prop in ["type", "host", "capability"]) {
                 if (expected[prop])
                   is(permission[prop], expected[prop],
                     "property: \"" + prop  + "\" should be equal");
               }
 
-              if (expected.origin) {
-                is(permission.principal.origin, expected.origin,
-                   "property: \"origin\" should be equal");
-              }
-
               os.removeObserver(permObserver, "perm-changed");
 
               if (testRunner.tests[testRunner._currentTest].cleanup) {
                 testRunner.tests[testRunner._currentTest].cleanup();
               }
 
               testRunner.dialog.close(params);
               win.close();
--- a/browser/components/preferences/tests/browser_permissions.js
+++ b/browser/components/preferences/tests/browser_permissions.js
@@ -110,32 +110,32 @@ var tests = [
 
     runNextTest();
   },
 
   function test_sites_list() {
     is(gSitesList.firstChild.id, "all-sites-item",
        "all sites is the first item in the sites list");
 
-    ok(getSiteItem(TEST_URI_1.prePath), "site item from places db exists");
-    ok(getSiteItem(TEST_URI_2.prePath), "site item from enumerating services exists");
+    ok(getSiteItem(TEST_URI_1.host), "site item from places db exists");
+    ok(getSiteItem(TEST_URI_2.host), "site item from enumerating services exists");
 
     runNextTest();
   },
 
   function test_filter_sites_list() {
     // set filter to test host
     let sitesFilter = gBrowser.contentDocument.getElementById("sites-filter");
     sitesFilter.value = TEST_URI_1.host;
     sitesFilter.doCommand();
 
     // make sure correct sites are collapsed/showing
-    let testSite1 = getSiteItem(TEST_URI_1.prePath);
+    let testSite1 = getSiteItem(TEST_URI_1.host);
     ok(!testSite1.collapsed, "test site 1 is not collapsed");
-    let testSite2 = getSiteItem(TEST_URI_2.prePath);
+    let testSite2 = getSiteItem(TEST_URI_2.host);
     ok(testSite2.collapsed, "test site 2 is collapsed");
 
     // clear filter
     sitesFilter.value = "";
     sitesFilter.doCommand();
 
     runNextTest();
   },
@@ -197,23 +197,23 @@ var tests = [
   function test_manage_all_cookies() {
     // make sure "Manage All Cookies..." button opens the correct dialog
     addWindowListener("chrome://browser/content/preferences/cookies.xul", runNextTest);
     gBrowser.contentDocument.getElementById("cookies-manage-all-button").doCommand();
   },
 
   function test_select_site() {
     // select the site that has the permissions we set at the beginning of the test
-    let testSiteItem = getSiteItem(TEST_URI_2.prePath);
+    let testSiteItem = getSiteItem(TEST_URI_2.host);
     gSitesList.selectedItem = testSiteItem;
 
     let siteHeader = gBrowser.contentDocument.getElementById("site-header");
     is(siteHeader, gHeaderDeck.selectedPanel,
        "correct header shown for a specific site");
-    is(gSiteLabel.value, TEST_URI_2.prePath, "header updated for selected site");
+    is(gSiteLabel.value, TEST_URI_2.host, "header updated for selected site");
 
     ok(!gBrowser.contentDocument.getElementById("passwords-count").hidden,
        "passwords count is not hidden");
     ok(!gBrowser.contentDocument.getElementById("cookies-count").hidden,
        "cookies count is not hidden");
 
     // Test to make sure "Allow" items are *not* hidden for certain permission types
     NO_GLOBAL_ALLOW.forEach(function(aType) {
@@ -278,17 +278,17 @@ var tests = [
     PlacesTestUtils.clearHistory().then(() => {
       is(gSiteLabel.value, "", "site label cleared");
 
       let allSitesItem = gBrowser.contentDocument.getElementById("all-sites-item");
       is(gSitesList.selectedItem, allSitesItem,
          "all sites item selected after forgetting selected site");
 
       // check to make sure site is gone from sites list
-      let testSiteItem = getSiteItem(TEST_URI_2.prePath);
+      let testSiteItem = getSiteItem(TEST_URI_2.host);
       ok(!testSiteItem, "site removed from sites list");
 
       // check to make sure we forgot all permissions corresponding to site
       for (let type in TEST_PERMS) {
         if (type == "password") {
           ok(Services.logins.getLoginSavingEnabled(TEST_URI_2.prePath),
              "password saving should be enabled by default");
         } else {
--- a/browser/components/preferences/translation.js
+++ b/browser/components/preferences/translation.js
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/BrowserUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "gLangBundle", () =>
   Services.strings.createBundle("chrome://global/locale/languageNames.properties"));
 
 const kPermissionType = "translate";
 const kLanguagesPref = "browser.translation.neverForLanguages";
 
 function Tree(aId, aData)
@@ -79,17 +78,17 @@ let gTranslationExceptions = {
     // Load site permissions into an array.
     this._sites = [];
     let enumerator = Services.perms.enumerator;
     while (enumerator.hasMoreElements()) {
       let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
 
       if (perm.type == kPermissionType &&
           perm.capability == Services.perms.DENY_ACTION) {
-        this._sites.push(perm.principal.origin);
+        this._sites.push(perm.host);
       }
     }
     Services.obs.addObserver(this, "perm-changed", false);
     this._sites.sort();
 
     this._siteTree = new Tree("sitesTree", this._sites);
     this.onSiteSelected();
 
@@ -122,24 +121,24 @@ let gTranslationExceptions = {
       else {
         let perm = aSubject.QueryInterface(Ci.nsIPermission);
         if (perm.type != kPermissionType)
           return;
 
         if (aData == "added") {
           if (perm.capability != Services.perms.DENY_ACTION)
             return;
-          this._sites.push(perm.principal.origin);
+          this._sites.push(perm.host);
           this._sites.sort();
           let boxObject = this._siteTree.boxObject;
           boxObject.rowCountChanged(0, 1);
           boxObject.invalidate();
         }
         else if (aData == "deleted") {
-          let index = this._sites.indexOf(perm.principal.origin);
+          let index = this._sites.indexOf(perm.host);
           if (index == -1)
             return;
           this._sites.splice(index, 1);
           this._siteTree.boxObject.rowCountChanged(index, -1);
           this.onSiteSelected();
           return;
         }
       }
@@ -184,32 +183,32 @@ let gTranslationExceptions = {
   },
 
   onAllLanguagesDeleted: function() {
     Services.prefs.setCharPref(kLanguagesPref, "");
   },
 
   onSiteDeleted: function() {
     let removedSites = this._siteTree.getSelectedItems();
-    for (let origin of removedSites) {
-      let principal = BrowserUtils.principalFromOrigin(origin);
-      Services.perms.removeFromPrincipal(principal, kPermissionType);
+    for (let host of removedSites) {
+      let uri = Services.io.newURI("http://" + host, null, null);
+      Services.perms.remove(uri, kPermissionType);
     }
   },
 
   onAllSitesDeleted: function() {
     if (this._siteTree.isEmpty)
       return;
 
     let removedSites = this._sites.splice(0, this._sites.length);
     this._siteTree.boxObject.rowCountChanged(0, -removedSites.length);
 
-    for (let origin of removedSites) {
-      let principal = BrowserUtils.principalFromOrigin(origin);
-      Services.perms.removeFromPrincipal(principal, kPermissionType);
+    for (let host of removedSites) {
+      let uri = Services.io.newURI("http://" + host, null, null);
+      Services.perms.remove(uri, kPermissionType);
     }
 
     this.onSiteSelected();
   },
 
   onSiteKeyPress: function(aEvent) {
     if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE)
       this.onSiteDeleted();
--- a/browser/components/translation/test/browser_translation_exceptions.js
+++ b/browser/components/translation/test/browser_translation_exceptions.js
@@ -46,17 +46,17 @@ function getLanguageExceptions() {
 function getDomainExceptions() {
   let results = [];
   let enumerator = Services.perms.enumerator;
   while (enumerator.hasMoreElements()) {
     let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
 
     if (perm.type == "translate" &&
         perm.capability == Services.perms.DENY_ACTION)
-      results.push(perm.principal);
+      results.push(perm.host);
   }
 
   return results;
 }
 
 function getInfoBar() {
   return gBrowser.getNotificationBox().getNotificationWithValue("translation");
 }
@@ -176,17 +176,17 @@ let gTests = [
 
     // Click the 'Never for French' item.
     notif._getAnonElt("neverForSite").click();
     ok(!getInfoBar(), "infobar hidden");
 
     // Check this has been saved to the exceptions list.
     let sites = getDomainExceptions();
     is(sites.length, 1, "one site in the exception list");
-    is(sites[0].origin, "http://example.com", "correct site in the exception list");
+    is(sites[0], "example.com", "correct site in the exception list");
     ok(!ui.shouldShowInfoBar(uri, "fr"),
        "the infobar wouldn't be shown anymore");
 
     // Reopen the infobar.
     PopupNotifications.getNotification("translate").anchorElement.click();
     notif = getInfoBar();
     // Open the "options" drop down.
     yield openPopup(notif._getAnonElt("options"));
--- a/browser/components/uitour/test/head.js
+++ b/browser/components/uitour/test/head.js
@@ -193,32 +193,29 @@ function loadUITourTestPage(callback, ho
     gContentAPI = gContentWindow.Mozilla.UITour;
 
     waitForFocus(callback, gContentWindow);
   }, true);
 }
 
 function UITourTest() {
   Services.prefs.setBoolPref("browser.uitour.enabled", true);
-  let testHttpsUri = Services.io.newURI("https://example.com", null, null);
-  let testHttpUri = Services.io.newURI("http://example.com", null, null);
-  Services.perms.add(testHttpsUri, "uitour", Services.perms.ALLOW_ACTION);
-  Services.perms.add(testHttpUri, "uitour", Services.perms.ALLOW_ACTION);
+  let testUri = Services.io.newURI("http://example.com", null, null);
+  Services.perms.add(testUri, "uitour", Services.perms.ALLOW_ACTION);
 
   waitForExplicitFinish();
 
   registerCleanupFunction(function() {
     delete window.gContentWindow;
     delete window.gContentAPI;
     if (gTestTab)
       gBrowser.removeTab(gTestTab);
     delete window.gTestTab;
     Services.prefs.clearUserPref("browser.uitour.enabled", true);
-    Services.perms.remove(testHttpsUri, "uitour");
-    Services.perms.remove(testHttpUri, "uitour");
+    Services.perms.remove(testUri, "uitour");
   });
 
   function done() {
     executeSoon(() => {
       if (gTestTab)
         gBrowser.removeTab(gTestTab);
       gTestTab = null;
 
--- a/browser/modules/PluginContent.jsm
+++ b/browser/modules/PluginContent.jsm
@@ -690,16 +690,30 @@ PluginContent.prototype = {
         overlay.removeEventListener("click", this, true);
       let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
       if (this.canActivatePlugin(objLoadingContent))
         this._handleClickToPlayEvent(plugin);
     }
     this._showClickToPlayNotification(null, false);
   },
 
+  // Match the behaviour of nsPermissionManager
+  _getHostFromPrincipal: function (principal) {
+    if (!principal.URI || principal.URI.schemeIs("moz-nullprincipal")) {
+      return "(null)";
+    }
+
+    try {
+      if (principal.URI.host)
+        return principal.URI.host;
+    } catch (e) {}
+
+    return principal.origin;
+  },
+
   /**
    * Activate the plugins that the user has specified.
    */
   activatePlugins: function (pluginInfo, newState) {
     let contentWindow = this.global.content;
     let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils);
     let plugins = cwu.plugins;
@@ -757,45 +771,47 @@ PluginContent.prototype = {
       }
     } else {
       plugins = [plugin];
     }
 
     let pluginData = this.pluginData;
 
     let principal = this.content.document.nodePrincipal;
+    let principalHost = this._getHostFromPrincipal(principal);
     let location = this.content.document.location.href;
 
     for (let p of plugins) {
       let pluginInfo = this._getPluginInfo(p);
       if (pluginInfo.permissionString === null) {
         Cu.reportError("No permission string for active plugin.");
         continue;
       }
       if (pluginData.has(pluginInfo.permissionString)) {
         continue;
       }
 
       let permissionObj = Services.perms.
         getPermissionObject(principal, pluginInfo.permissionString, false);
       if (permissionObj) {
-        pluginInfo.pluginPermissionPrePath = permissionObj.principal.originNoSuffix;
+        pluginInfo.pluginPermissionHost = permissionObj.host;
         pluginInfo.pluginPermissionType = permissionObj.expireType;
       }
       else {
-        pluginInfo.pluginPermissionPrePath = principal.originNoSuffix;
+        pluginInfo.pluginPermissionHost = principalHost;
         pluginInfo.pluginPermissionType = undefined;
       }
 
       this.pluginData.set(pluginInfo.permissionString, pluginInfo);
     }
 
     this.global.sendAsyncMessage("PluginContent:ShowClickToPlayNotification", {
       plugins: [... this.pluginData.values()],
       showNow: showNow,
+      host: principalHost,
       location: location,
     }, null, principal);
   },
 
   /**
    * Updates the "hidden plugin" notification bar UI.
    *
    * @param document (optional)
@@ -868,16 +884,17 @@ PluginContent.prototype = {
       }
     }
 
     // If there are any items remaining in `actions` now, they are hidden
     // plugins that need a notification bar.
     this.global.sendAsyncMessage("PluginContent:UpdateHiddenPluginUI", {
       haveInsecure: haveInsecure,
       actions: [... actions.values()],
+      host: this._getHostFromPrincipal(principal),
       location: location,
     }, null, principal);
   },
 
   removeNotification: function (name) {
     this.global.sendAsyncMessage("PluginContent:RemoveNotification", { name: name });
   },
 
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -46,17 +46,17 @@ OriginAttributes::CreateSuffix(nsACStrin
   if (!mAddonId.IsEmpty()) {
     params->Set(NS_LITERAL_STRING("addonId"), mAddonId);
   }
 
   aStr.Truncate();
 
   params->Serialize(value);
   if (!value.IsEmpty()) {
-    aStr.AppendLiteral("^");
+    aStr.AppendLiteral("!");
     aStr.Append(NS_ConvertUTF16toUTF8(value));
   }
 }
 
 namespace {
 
 class MOZ_STACK_CLASS PopulateFromSuffixIterator final
   : public URLParams::ForEachIterator
@@ -112,34 +112,34 @@ private:
 
 bool
 OriginAttributes::PopulateFromSuffix(const nsACString& aStr)
 {
   if (aStr.IsEmpty()) {
     return true;
   }
 
-  if (aStr[0] != '^') {
+  if (aStr[0] != '!') {
     return false;
   }
 
   UniquePtr<URLParams> params(new URLParams());
   params->ParseInput(Substring(aStr, 1, aStr.Length() - 1));
 
   PopulateFromSuffixIterator iterator(this);
   return params->ForEach(iterator);
 }
 
 bool
 OriginAttributes::PopulateFromOrigin(const nsACString& aOrigin,
                                      nsACString& aOriginNoSuffix)
 {
   // RFindChar is only available on nsCString.
   nsCString origin(aOrigin);
-  int32_t pos = origin.RFindChar('^');
+  int32_t pos = origin.RFindChar('!');
 
   if (pos == kNotFound) {
     aOriginNoSuffix = origin;
     return true;
   }
 
   aOriginNoSuffix = Substring(origin, 0, pos);
   return PopulateFromSuffix(Substring(origin, pos));
--- a/caps/nsPrincipal.cpp
+++ b/caps/nsPrincipal.cpp
@@ -9,17 +9,16 @@
 #include "mozIThirdPartyUtil.h"
 #include "nscore.h"
 #include "nsScriptSecurityManager.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "pratom.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
-#include "nsIStandardURL.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsJSPrincipals.h"
 #include "nsIEffectiveTLDService.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIProtocolHandler.h"
 #include "nsError.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsNetCID.h"
@@ -123,41 +122,16 @@ nsPrincipal::GetOriginForURI(nsIURI* aUR
     rv = origin->GetAsciiHost(hostPort);
     // Some implementations return an empty string, treat it as no support
     // for asciiHost by that implementation.
     if (hostPort.IsEmpty()) {
       rv = NS_ERROR_FAILURE;
     }
   }
 
-  // We want the invariant that prinA.origin == prinB.origin i.f.f.
-  // prinA.equals(prinB). However, this requires that we impose certain constraints
-  // on the behavior and origin semantics of principals, and in particular, forbid
-  // creating origin strings for principals whose equality constraints are not
-  // expressible as strings (i.e. object equality). Moreover, we want to forbid URIs
-  // containing the magic "^" we use as a separating character for origin
-  // attributes.
-  //
-  // These constraints can generally be achieved by restricting .origin to
-  // nsIStandardURL-based URIs, but there are a few other URI schemes that we need
-  // to handle.
-  bool isBehaved;
-  if ((NS_SUCCEEDED(origin->SchemeIs("about", &isBehaved)) && isBehaved) ||
-      (NS_SUCCEEDED(origin->SchemeIs("moz-safe-about", &isBehaved)) && isBehaved) ||
-      (NS_SUCCEEDED(origin->SchemeIs("indexeddb", &isBehaved)) && isBehaved)) {
-    rv = origin->GetAsciiSpec(aOrigin);
-    NS_ENSURE_SUCCESS(rv, rv);
-    // These URIs could technically contain a '^', but they never should.
-    if (NS_WARN_IF(aOrigin.FindChar('^', 0) != -1)) {
-      aOrigin.Truncate();
-      return NS_ERROR_FAILURE;
-    }
-    return NS_OK;
-  }
-
   int32_t port;
   if (NS_SUCCEEDED(rv) && !isChrome) {
     rv = origin->GetPort(&port);
   }
 
   if (NS_SUCCEEDED(rv) && !isChrome) {
     if (port != -1) {
       hostPort.Append(':');
@@ -165,24 +139,16 @@ nsPrincipal::GetOriginForURI(nsIURI* aUR
     }
 
     rv = origin->GetScheme(aOrigin);
     NS_ENSURE_SUCCESS(rv, rv);
     aOrigin.AppendLiteral("://");
     aOrigin.Append(hostPort);
   }
   else {
-    // If we reached this branch, we can only create an origin if we have a nsIStandardURL.
-    // So, we query to a nsIStandardURL, and fail if we aren't an instance of an nsIStandardURL
-    // nsIStandardURLs have the good property of escaping the '^' character in their specs,
-    // which means that we can be sure that the caret character (which is reserved for delimiting
-    // the end of the spec, and the beginning of the origin attributes) is not present in the
-    // origin string
-    nsCOMPtr<nsIStandardURL> standardURL = do_QueryInterface(origin);
-    NS_ENSURE_TRUE(standardURL, NS_ERROR_FAILURE);
     rv = origin->GetAsciiSpec(aOrigin);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 nsresult
--- a/caps/tests/unit/test_origin.js
+++ b/caps/tests/unit/test_origin.js
@@ -63,43 +63,43 @@ function run_test() {
 
   //
   // Test origin attributes.
   //
 
   // Just app.
   var exampleOrg_app = ssm.createCodebasePrincipal(makeURI('http://example.org'), {appId: 42});
   var nullPrin_app = ssm.createNullPrincipal({appId: 42});
-  checkOriginAttributes(exampleOrg_app, {appId: 42}, '^appId=42');
-  checkOriginAttributes(nullPrin_app, {appId: 42}, '^appId=42');
-  do_check_eq(exampleOrg_app.origin, 'http://example.org^appId=42');
+  checkOriginAttributes(exampleOrg_app, {appId: 42}, '!appId=42');
+  checkOriginAttributes(nullPrin_app, {appId: 42}, '!appId=42');
+  do_check_eq(exampleOrg_app.origin, 'http://example.org!appId=42');
 
   // Just browser.
   var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true});
   var nullPrin_browser = ssm.createNullPrincipal({inBrowser: true});
-  checkOriginAttributes(exampleOrg_browser, {inBrowser: true}, '^inBrowser=1');
-  checkOriginAttributes(nullPrin_browser, {inBrowser: true}, '^inBrowser=1');
-  do_check_eq(exampleOrg_browser.origin, 'http://example.org^inBrowser=1');
+  checkOriginAttributes(exampleOrg_browser, {inBrowser: true}, '!inBrowser=1');
+  checkOriginAttributes(nullPrin_browser, {inBrowser: true}, '!inBrowser=1');
+  do_check_eq(exampleOrg_browser.origin, 'http://example.org!inBrowser=1');
 
   // App and browser.
   var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true, appId: 42});
   var nullPrin_appBrowser = ssm.createNullPrincipal({inBrowser: true, appId: 42});
-  checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
-  checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
-  do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org^appId=42&inBrowser=1');
+  checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1');
+  checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1');
+  do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org!appId=42&inBrowser=1');
 
   // App and browser, different domain.
   var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {appId: 42, inBrowser: true});
-  checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
-  do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123^appId=42&inBrowser=1');
+  checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1');
+  do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123!appId=42&inBrowser=1');
 
   // Addon.
   var exampleOrg_addon = ssm.createCodebasePrincipal(makeURI('http://example.org'), {addonId: 'dummy'});
-  checkOriginAttributes(exampleOrg_addon, { addonId: "dummy" }, '^addonId=dummy');
-  do_check_eq(exampleOrg_addon.origin, 'http://example.org^addonId=dummy');
+  checkOriginAttributes(exampleOrg_addon, { addonId: "dummy" }, '!addonId=dummy');
+  do_check_eq(exampleOrg_addon.origin, 'http://example.org!addonId=dummy');
 
   // Check that all of the above are cross-origin.
   checkCrossOrigin(exampleOrg_app, exampleOrg);
   checkCrossOrigin(exampleOrg_app, nullPrin_app);
   checkCrossOrigin(exampleOrg_browser, exampleOrg_app);
   checkCrossOrigin(exampleOrg_browser, nullPrin_browser);
   checkCrossOrigin(exampleOrg_appBrowser, exampleOrg_app);
   checkCrossOrigin(exampleOrg_appBrowser, nullPrin_appBrowser);
--- a/dom/apps/tests/unit/test_moziapplication.js
+++ b/dom/apps/tests/unit/test_moziapplication.js
@@ -46,17 +46,17 @@ add_test(() => {
     if (key == "principal") {
       return;
     }
     Assert.equal(app[key], mozapp[key],
                  "app[" + key + "] should be equal to mozapp[" + key + "]");
   });
 
   Assert.ok(mozapp.principal, "app principal should exist");
-  let expectedPrincipalOrigin = app.origin + "^appId=" + app.localId;
+  let expectedPrincipalOrigin = app.origin + "!appId=" + app.localId;
   Assert.equal(mozapp.principal.origin, expectedPrincipalOrigin,
                "app principal origin ok");
   Assert.equal(mozapp.principal.appId, app.localId, "app principal appId ok");
   Assert.equal(mozapp.principal.isInBrowserElement, false,
                "app principal isInBrowserElement ok");
   run_next_test();
 });
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -48,17 +48,16 @@
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/layers/SharedBufferManagerChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/plugins/PluginModuleParent.h"
 #include "mozilla/widget/WidgetMessageUtils.h"
 #include "mozilla/media/MediaChild.h"
-#include "mozilla/BasePrincipal.h"
 
 #if defined(MOZ_CONTENT_SANDBOX)
 #if defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
 #include "mozilla/sandboxTarget.h"
 #elif defined(XP_LINUX)
 #include "mozilla/Sandbox.h"
 #include "mozilla/SandboxInfo.h"
@@ -2108,26 +2107,29 @@ ContentChild::RecvAddPermission(const IP
 #if MOZ_PERMISSIONS
     nsCOMPtr<nsIPermissionManager> permissionManagerIface =
         services::GetPermissionManager();
     nsPermissionManager* permissionManager =
         static_cast<nsPermissionManager*>(permissionManagerIface.get());
     MOZ_ASSERT(permissionManager,
                "We have no permissionManager in the Content process !");
 
-    nsAutoCString originNoSuffix;
-    OriginAttributes attrs;
-    attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
-
     nsCOMPtr<nsIURI> uri;
-    nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
+    NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host));
+    NS_ENSURE_TRUE(uri, true);
+
+    nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
+    MOZ_ASSERT(secMan);
+
+    nsCOMPtr<nsIPrincipal> principal;
+    nsresult rv = secMan->GetAppCodebasePrincipal(uri, permission.appId,
+                                                permission.isInBrowserElement,
+                                                getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, true);
 
-    nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs);
-
     // child processes don't care about modification time.
     int64_t modificationTime = 0;
 
     permissionManager->AddInternal(principal,
                                    nsCString(permission.type),
                                    permission.capability,
                                    0,
                                    permission.expireType,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2554,32 +2554,33 @@ ContentParent::RecvReadPermissions(Infal
         enumerator->HasMoreElements(&hasMore);
         if (!hasMore)
             break;
 
         nsCOMPtr<nsISupports> supp;
         enumerator->GetNext(getter_AddRefs(supp));
         nsCOMPtr<nsIPermission> perm = do_QueryInterface(supp);
 
-        nsCOMPtr<nsIPrincipal> principal;
-        perm->GetPrincipal(getter_AddRefs(principal));
-        nsCString origin;
-        if (principal) {
-            principal->GetOrigin(origin);
-        }
+        nsCString host;
+        perm->GetHost(host);
+        uint32_t appId;
+        perm->GetAppId(&appId);
+        bool isInBrowserElement;
+        perm->GetIsInBrowserElement(&isInBrowserElement);
         nsCString type;
         perm->GetType(type);
         uint32_t capability;
         perm->GetCapability(&capability);
         uint32_t expireType;
         perm->GetExpireType(&expireType);
         int64_t expireTime;
         perm->GetExpireTime(&expireTime);
 
-        aPermissions->AppendElement(IPC::Permission(origin, type,
+        aPermissions->AppendElement(IPC::Permission(host, appId,
+                                                    isInBrowserElement, type,
                                                     capability, expireType,
                                                     expireTime));
     }
 
     // Ask for future changes
     mSendPermissionUpdates = true;
 #endif
 
--- a/dom/storage/DOMStorageObserver.cpp
+++ b/dom/storage/DOMStorageObserver.cpp
@@ -191,30 +191,18 @@ DOMStorageObserver::Observe(nsISupports*
 
     uint32_t cap = 0;
     perm->GetCapability(&cap);
     if (!(cap & nsICookiePermission::ACCESS_SESSION) ||
         !NS_LITERAL_STRING("deleted").Equals(nsDependentString(aData))) {
       return NS_OK;
     }
 
-    nsCOMPtr<nsIPrincipal> principal;
-    perm->GetPrincipal(getter_AddRefs(principal));
-    if (!principal) {
-      return NS_OK;
-    }
-
-    nsCOMPtr<nsIURI> origin;
-    principal->GetURI(getter_AddRefs(origin));
-    if (!origin) {
-      return NS_OK;
-    }
-
     nsAutoCString host;
-    origin->GetHost(host);
+    perm->GetHost(host);
     if (host.IsEmpty()) {
       return NS_OK;
     }
 
     nsAutoCString scope;
     rv = CreateReversedDomain(host, scope);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/extensions/cookie/nsPermission.cpp
+++ b/extensions/cookie/nsPermission.cpp
@@ -1,42 +1,56 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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/. */
 
 #include "nsPermission.h"
-#include "nsContentUtils.h"
 #include "nsIClassInfoImpl.h"
-#include "nsIEffectiveTLDService.h"
-#include "mozilla/BasePrincipal.h"
 
 // nsPermission Implementation
 
 NS_IMPL_CLASSINFO(nsPermission, nullptr, 0, {0})
 NS_IMPL_ISUPPORTS_CI(nsPermission, nsIPermission)
 
-nsPermission::nsPermission(nsIPrincipal*    aPrincipal,
+nsPermission::nsPermission(const nsACString &aHost,
+                           uint32_t aAppId,
+                           bool aIsInBrowserElement,
                            const nsACString &aType,
                            uint32_t         aCapability,
                            uint32_t         aExpireType,
                            int64_t          aExpireTime)
- : mPrincipal(aPrincipal)
+ : mHost(aHost)
  , mType(aType)
  , mCapability(aCapability)
  , mExpireType(aExpireType)
  , mExpireTime(aExpireTime)
+ , mAppId(aAppId)
+ , mIsInBrowserElement(aIsInBrowserElement)
 {
 }
 
 NS_IMETHODIMP
-nsPermission::GetPrincipal(nsIPrincipal** aPrincipal)
+nsPermission::GetHost(nsACString &aHost)
+{
+  aHost = mHost;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPermission::GetAppId(uint32_t* aAppId)
 {
-  nsCOMPtr<nsIPrincipal> copy = mPrincipal;
-  copy.forget(aPrincipal);
+  *aAppId = mAppId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPermission::GetIsInBrowserElement(bool* aIsInBrowserElement)
+{
+  *aIsInBrowserElement = mIsInBrowserElement;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPermission::GetType(nsACString &aType)
 {
   aType = mType;
   return NS_OK;
@@ -57,122 +71,8 @@ nsPermission::GetExpireType(uint32_t *aE
 }
 
 NS_IMETHODIMP
 nsPermission::GetExpireTime(int64_t *aExpireTime)
 {
   *aExpireTime = mExpireTime;
   return NS_OK;
 }
-
-NS_IMETHODIMP
-nsPermission::Matches(nsIPrincipal* aPrincipal, bool aExactHost, bool* aMatches)
-{
-  NS_ENSURE_ARG_POINTER(aPrincipal);
-  NS_ENSURE_ARG_POINTER(aMatches);
-
-  *aMatches = false;
-
-  // If the principals are equal, then they match.
-  if (mPrincipal->Equals(aPrincipal)) {
-    *aMatches = true;
-    return NS_OK;
-  }
-
-  // If we are matching with an exact host, we're done now - the permissions don't match
-  // otherwise, we need to start comparing subdomains!
-  if (aExactHost) {
-      return NS_OK;
-  }
-
-  // Compare their OriginAttributes
-  const mozilla::OriginAttributes& theirAttrs = mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
-  const mozilla::OriginAttributes& ourAttrs = mozilla::BasePrincipal::Cast(mPrincipal)->OriginAttributesRef();
-
-  if (theirAttrs != ourAttrs) {
-      return NS_OK;
-  }
-
-  nsCOMPtr<nsIURI> theirURI;
-  nsresult rv = aPrincipal->GetURI(getter_AddRefs(theirURI));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIURI> ourURI;
-  rv = mPrincipal->GetURI(getter_AddRefs(ourURI));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Compare schemes
-  nsAutoCString theirScheme;
-  rv = theirURI->GetScheme(theirScheme);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoCString ourScheme;
-  rv = ourURI->GetScheme(ourScheme);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (theirScheme != ourScheme) {
-    return NS_OK;
-  }
-
-  // Compare ports
-  int32_t theirPort;
-  rv = theirURI->GetPort(&theirPort);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  int32_t ourPort;
-  rv = ourURI->GetPort(&ourPort);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (theirPort != ourPort) {
-    return NS_OK;
-  }
-
-  // Check if the host or any subdomain of their host matches.
-  nsAutoCString theirHost;
-  rv = theirURI->GetHost(theirHost);
-  if (NS_FAILED(rv) || theirHost.IsEmpty()) {
-    return NS_OK;
-  }
-
-  nsAutoCString ourHost;
-  rv = ourURI->GetHost(ourHost);
-  if (NS_FAILED(rv) || ourHost.IsEmpty()) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIEffectiveTLDService> tldService =
-    do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
-  if (!tldService) {
-    NS_ERROR("Should have a tld service!");
-    return NS_ERROR_FAILURE;
-  }
-
-  // This loop will not loop forever, as GetNextSubDomain will eventually fail
-  // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
-  while (theirHost != ourHost) {
-    rv = tldService->GetNextSubDomain(theirHost, theirHost);
-    if (NS_FAILED(rv)) {
-      if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
-        return NS_OK;
-      } else {
-        return rv;
-      }
-    }
-  }
-
-  *aMatches = true;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPermission::MatchesURI(nsIURI* aURI, bool aExactHost, bool* aMatches)
-{
-  NS_ENSURE_ARG_POINTER(aURI);
-
-  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIPrincipal> principal;
-  nsresult rv = secMan->GetNoAppCodebasePrincipal(aURI, getter_AddRefs(principal));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return Matches(principal, aExactHost, aMatches);
-}
--- a/extensions/cookie/nsPermission.h
+++ b/extensions/cookie/nsPermission.h
@@ -13,25 +13,29 @@
 
 class nsPermission : public nsIPermission
 {
 public:
   // nsISupports
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPERMISSION
 
-  nsPermission(nsIPrincipal* aPrincipal,
+  nsPermission(const nsACString &aHost,
+               uint32_t aAppId,
+               bool aIsInBrowserElement,
                const nsACString &aType,
                uint32_t aCapability,
                uint32_t aExpireType,
                int64_t aExpireTime);
 
 protected:
   virtual ~nsPermission() {};
 
-  nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsCString mHost;
   nsCString mType;
   uint32_t  mCapability;
   uint32_t  mExpireType;
   int64_t   mExpireTime;
+  uint32_t  mAppId;
+  bool      mIsInBrowserElement;
 };
 
 #endif // nsPermission_h__
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -3,17 +3,16 @@
  * 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/. */
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentChild.h"
-#include "mozilla/BasePrincipal.h"
 #include "mozilla/unused.h"
 #include "nsPermissionManager.h"
 #include "nsPermission.h"
 #include "nsCRT.h"
 #include "nsNetUtil.h"
 #include "nsCOMArray.h"
 #include "nsArrayEnumerator.h"
 #include "nsTArray.h"
@@ -35,18 +34,16 @@
 #include "nsIEffectiveTLDService.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocument.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "mozilla/Preferences.h"
 #include "nsReadLine.h"
 #include "mozilla/Telemetry.h"
 #include "nsIConsoleService.h"
-#include "nsINavHistoryService.h"
-#include "nsToolkitCompsCID.h"
 
 static nsPermissionManager *gPermissionManager = nullptr;
 
 using mozilla::dom::ContentParent;
 using mozilla::dom::ContentChild;
 using mozilla::unused; // ha!
 
 static bool
@@ -99,52 +96,94 @@ LogToConsole(const nsAString& aMsg)
 #define ENSURE_NOT_CHILD_PROCESS_NORET \
   ENSURE_NOT_CHILD_PROCESS_(;)
 
 ////////////////////////////////////////////////////////////////////////////////
 
 namespace {
 
 nsresult
-GetPrincipalFromOrigin(const nsACString& aOrigin, nsIPrincipal** aPrincipal)
-{
-  nsAutoCString originNoSuffix;
-  mozilla::OriginAttributes attrs;
-  if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs);
-  principal.forget(aPrincipal);
-  return NS_OK;
-}
-
-
-nsresult
-GetPrincipal(nsIURI* aURI, uint32_t aAppId, bool aIsInBrowserElement, nsIPrincipal** aPrincipal)
+GetPrincipal(const nsACString& aHost, uint32_t aAppId, bool aIsInBrowserElement,
+             nsIPrincipal** aPrincipal)
 {
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
   NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
 
-  return secMan->GetAppCodebasePrincipal(aURI, aAppId, aIsInBrowserElement, aPrincipal);
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_NewURI(getter_AddRefs(uri), aHost);
+  if (NS_FAILED(rv)) {
+    // NOTE: most callers will end up here because we don't append "http://" for
+    // hosts. It's fine to arbitrary use "http://" because, for those entries,
+    // we will actually just use the host. If we end up here, but the host looks
+    // like an email address, we use mailto: instead.
+    nsCString scheme;
+    if (aHost.FindChar('@') == -1)
+      scheme = NS_LITERAL_CSTRING("http://");
+    else
+      scheme = NS_LITERAL_CSTRING("mailto:");
+    rv = NS_NewURI(getter_AddRefs(uri), scheme + aHost);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return secMan->GetAppCodebasePrincipal(uri, aAppId, aIsInBrowserElement, aPrincipal);
 }
 
 nsresult
 GetPrincipal(nsIURI* aURI, nsIPrincipal** aPrincipal)
 {
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
   NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
 
   return secMan->GetNoAppCodebasePrincipal(aURI, aPrincipal);
 }
 
+nsresult
+GetPrincipal(const nsACString& aHost, nsIPrincipal** aPrincipal)
+{
+  return GetPrincipal(aHost, nsIScriptSecurityManager::NO_APP_ID, false, aPrincipal);
+}
+
+nsresult
+GetHostForPrincipal(nsIPrincipal* aPrincipal, nsACString& aHost)
+{
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  uri = NS_GetInnermostURI(uri);
+  NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
+
+  rv = uri->GetAsciiHost(aHost);
+  if (NS_SUCCEEDED(rv) && !aHost.IsEmpty()) {
+    return NS_OK;
+  }
+
+  // For the mailto scheme, we use the path of the URI. We have to chop off the
+  // query part if one exists, so we eliminate everything after a ?.
+  bool isMailTo = false;
+  if (NS_SUCCEEDED(uri->SchemeIs("mailto", &isMailTo)) && isMailTo) {
+    rv = uri->GetPath(aHost);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    int32_t spart = aHost.FindChar('?', 0);
+    if (spart >= 0) {
+      aHost.Cut(spart, aHost.Length() - spart);
+    }
+    return NS_OK;
+  }
+
+  // Some entries like "file://" uses the origin.
+  rv = aPrincipal->GetOriginNoSuffix(aHost);
+  if (NS_SUCCEEDED(rv) && !aHost.IsEmpty()) {
+    return NS_OK;
+  }
+
+  return NS_ERROR_UNEXPECTED;
+}
+
 nsCString
 GetNextSubDomainForHost(const nsACString& aHost)
 {
   nsCOMPtr<nsIEffectiveTLDService> tldService =
     do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
   if (!tldService) {
     NS_ERROR("Should have a tld service!");
     return EmptyCString();
@@ -190,289 +229,32 @@ public:
 
     nsCOMPtr<nsIPermissionManager> permManager = do_GetService("@mozilla.org/permissionmanager;1");
     return permManager->RemovePermissionsForApp(appId, browserOnly);
   }
 };
 
 NS_IMPL_ISUPPORTS(AppClearDataObserver, nsIObserver)
 
-class MOZ_STACK_CLASS UpgradeHostToOriginHelper {
-public:
-  virtual nsresult Insert(nsIPrincipal* aPrincipal, const nsAFlatCString& aType,
-                      uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
-                      int64_t aModificationTime) = 0;
-};
-
-class UpgradeHostToOriginDBMigration final : public UpgradeHostToOriginHelper {
-public:
-  UpgradeHostToOriginDBMigration(mozIStorageConnection* aDBConn, int64_t* aID) : mDBConn(aDBConn)
-                                                                               , mID(aID)
-  {
-    mDBConn->CreateStatement(NS_LITERAL_CSTRING(
-      "INSERT INTO moz_hosts_new "
-      "(id, origin, type, permission, expireType, expireTime, modificationTime) "
-      "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"), getter_AddRefs(mInsertStmt));
-
-    mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT id FROM moz_hosts_new WHERE origin = ?1"),
-                             getter_AddRefs(mLookupStmt));
-  }
-
-  nsresult
-  Insert(nsIPrincipal* aPrincipal, const nsAFlatCString& aType,
-         uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
-         int64_t aModificationTime) final
-  {
-    nsAutoCString origin;
-    nsresult rv = aPrincipal->GetOrigin(origin);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mLookupStmt->Reset();
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mLookupStmt->BindUTF8StringByIndex(0, origin);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // Check to see if the origin already exists in the database
-    bool hasResult = false;
-    if (NS_SUCCEEDED(mLookupStmt->ExecuteStep(&hasResult)) && hasResult) {
-      mLookupStmt->Reset();
-      return NS_OK;
-    }
-
-    rv = mInsertStmt->BindInt64ByIndex(0, *mID);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mInsertStmt->BindUTF8StringByIndex(1, origin);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mInsertStmt->BindUTF8StringByIndex(2, aType);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mInsertStmt->BindInt32ByIndex(3, aPermission);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mInsertStmt->BindInt32ByIndex(4, aExpireType);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mInsertStmt->BindInt64ByIndex(5, aExpireTime);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mInsertStmt->BindInt64ByIndex(6, aModificationTime);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // Increment the working identifier, as we are about to use this one
-    (*mID)++;
-
-    rv = mInsertStmt->Execute();
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return NS_OK;
-  }
-
-private:
-  nsCOMPtr<mozIStorageStatement> mLookupStmt;
-  nsCOMPtr<mozIStorageStatement> mInsertStmt;
-  nsCOMPtr<mozIStorageConnection> mDBConn;
-  int64_t* mID;
-};
-
-class UpgradeHostToOriginHostfileImport final : public UpgradeHostToOriginHelper {
-public:
-  UpgradeHostToOriginHostfileImport(nsPermissionManager* aPm,
-                                    nsPermissionManager::DBOperationType aOperation,
-                                    int64_t aID) : mPm(aPm)
-                                                 , mOperation(aOperation)
-                                                 , mID(aID)
-  {}
-
-  nsresult
-  Insert(nsIPrincipal* aPrincipal, const nsAFlatCString& aType,
-         uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
-         int64_t aModificationTime) final
-  {
-    // AddInternal won't do anything if the permission already exists
-    return mPm->AddInternal(aPrincipal, aType, aPermission, mID,
-                            aExpireType, aExpireTime, aModificationTime,
-                            nsPermissionManager::eDontNotify, mOperation);
-  }
-
-private:
-  nsRefPtr<nsPermissionManager> mPm;
-  nsPermissionManager::DBOperationType mOperation;
-  int64_t mID;
-};
-
-nsresult
-UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aType,
-                             uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
-                             int64_t aModificationTime, uint32_t aAppId, bool aIsInBrowserElement,
-                             UpgradeHostToOriginHelper* aHelper)
-{
-  if (aHost.EqualsLiteral("<file>")) {
-    // We no longer support the magic host <file>
-    NS_WARNING("The magic host <file> is no longer supported. "
-               "It is being removed from the permissions database.");
-    return NS_OK;
-  }
-
-  // First, we check to see if the host is a valid URI. If it is, it can be imported directly
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = NS_NewURI(getter_AddRefs(uri), aHost);
-  if (NS_SUCCEEDED(rv)) {
-    // It was previously possible to insert useless entries to your permissions database
-    // for URIs which have a null principal. This acts as a cleanup, getting rid of
-    // these useless database entries
-    bool nullpScheme = false;
-    if (NS_SUCCEEDED(uri->SchemeIs("moz-nullprincipal", &nullpScheme)) && nullpScheme) {
-      NS_WARNING("A moz-nullprincipal: permission is being discarded.");
-      return NS_OK;
-    }
-
-    nsCOMPtr<nsIPrincipal> principal;
-    rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return aHelper->Insert(principal, aType, aPermission,
-                           aExpireType, aExpireTime, aModificationTime);
-    return NS_OK;
-  }
-
-  // The user may use this host at non-standard ports or protocols, we can use their history
-  // to guess what ports and protocols we want to add permissions for.
-  // We find every URI which they have visited with this host (or a subdomain of this host),
-  // and try to add it as a principal.
-  nsCOMPtr<nsINavHistoryService> histSrv = do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
-
-  nsCOMPtr<nsINavHistoryQuery> histQuery;
-  rv = histSrv->GetNewQuery(getter_AddRefs(histQuery));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // We want to only find history items for this particular host, and subdomains
-  rv = histQuery->SetDomain(aHost);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = histQuery->SetDomainIsHost(false);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsINavHistoryQueryOptions> histQueryOpts;
-  rv = histSrv->GetNewQueryOptions(getter_AddRefs(histQueryOpts));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // We want to get the URIs for every item in the user's history with the given host
-  rv = histQueryOpts->SetResultType(nsINavHistoryQueryOptions::RESULTS_AS_URI);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // We only search history, because searching both bookmarks and history
-  // is not supported, and history tends to be more comprehensive.
-  rv = histQueryOpts->SetQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // We include hidden URIs (such as those visited via iFrames) as they may have permissions too
-  rv = histQueryOpts->SetIncludeHidden(true);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsINavHistoryResult> histResult;
-  rv = histSrv->ExecuteQuery(histQuery, histQueryOpts, getter_AddRefs(histResult));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsINavHistoryContainerResultNode> histResultContainer;
-  rv = histResult->GetRoot(getter_AddRefs(histResultContainer));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = histResultContainer->SetContainerOpen(true);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  uint32_t childCount = 0;
-  rv = histResultContainer->GetChildCount(&childCount);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  bool foundHistory = false;
-  for (uint32_t i = 0; i < childCount; i++) {
-    nsCOMPtr<nsINavHistoryResultNode> child;
-    histResultContainer->GetChild(i, getter_AddRefs(child));
-    if (NS_FAILED(rv)) continue;
-
-    uint32_t type;
-    rv = child->GetType(&type);
-    if (NS_FAILED(rv) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) {
-      NS_WARNING("Unexpected non-RESULT_TYPE_URI node in "
-                 "UpgradeHostToOriginAndInsert()");
-      continue;
-    }
-
-    nsAutoCString uriSpec;
-    rv = child->GetUri(uriSpec);
-    if (NS_FAILED(rv)) continue;
-
-    nsCOMPtr<nsIURI> uri;
-    rv = NS_NewURI(getter_AddRefs(uri), uriSpec);
-    if (NS_FAILED(rv)) continue;
-
-    // Use the provided host - this URI may be for a subdomain, rather than the host we care about.
-    rv = uri->SetHost(aHost);
-    if (NS_FAILED(rv)) continue;
-
-    // We now have a URI which we can make a nsIPrincipal out of
-    nsCOMPtr<nsIPrincipal> principal;
-    rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
-    if (NS_FAILED(rv)) continue;
-
-    // Insert it! (The backend should be able to deal with us inserting the same origin repeatedly)
-    foundHistory = true;
-    rv = aHelper->Insert(principal, aType, aPermission,
-                         aExpireType, aExpireTime, aModificationTime);
-    NS_WARN_IF(NS_FAILED(rv));
-  }
-
-  rv = histResultContainer->SetContainerOpen(false);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // If we didn't find any origins for this host in the poermissions database,
-  // we can insert the default http:// and https:// permissions into the database.
-  // This has a relatively high liklihood of applying the permission to the correct
-  // origin.
-  if (!foundHistory) {
-    rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + aHost);
-    if (NS_SUCCEEDED(rv)) {
-      nsCOMPtr<nsIPrincipal> principal;
-      rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      aHelper->Insert(principal, aType, aPermission,
-                      aExpireType, aExpireTime, aModificationTime);
-    }
-    rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("https://") + aHost);
-    if (NS_SUCCEEDED(rv)) {
-      nsCOMPtr<nsIPrincipal> principal;
-      rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      aHelper->Insert(principal, aType, aPermission,
-                      aExpireType, aExpireTime, aModificationTime);
-    }
-  }
-
-  return NS_OK;
-}
-
 static bool
 IsExpandedPrincipal(nsIPrincipal* aPrincipal)
 {
   nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(aPrincipal);
   return !!ep;
 }
 
 } // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
 
 nsPermissionManager::PermissionKey::PermissionKey(nsIPrincipal* aPrincipal)
 {
-  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetOrigin(mOrigin)));
+  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(GetHostForPrincipal(aPrincipal, mHost)));
+  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetAppId(&mAppId)));
+  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetIsInBrowserElement(&mIsInBrowserElement)));
 }
 
 /**
  * Simple callback used by |AsyncClose| to trigger a treatment once
  * the database is closed.
  *
  * Note: Beware that, if you hold onto a |CloseDatabaseListener| from a
  * |nsPermissionManager|, this will create a cycle.
@@ -585,17 +367,17 @@ nsPermissionManager::AppClearDataObserve
   nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
   observerService->AddObserver(new AppClearDataObserver(), "webapps-clear-data", /* holdsWeak= */ false);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsPermissionManager Implementation
 
 #define PERMISSIONS_FILE_NAME "permissions.sqlite"
-#define HOSTS_SCHEMA_VERSION 5
+#define HOSTS_SCHEMA_VERSION 4
 
 #define HOSTPERM_FILE_NAME "hostperm.1"
 
 // Default permissions are read from a URL - this is the preference we read
 // to find that URL. If not set, don't use any default permissions.
 static const char kDefaultsUrlPrefName[] = "permissions.manager.defaultsUrl";
 
 static const char kPermissionChangeNotification[] = PERM_CHANGE_NOTIFICATION;
@@ -828,115 +610,32 @@ nsPermissionManager::InitDB(bool aRemove
         // within the first hour after migration would remove all permissions.
 
         rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       // fall through to the next upgrade
 
-    // Version 4->5 is the merging of host, appId, and isInBrowserElement into origin
-    case 4:
-      {
-        bool tableExists = false;
-        mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_new"), &tableExists);
-        if (tableExists) {
-          rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_hosts_new"));
-          NS_ENSURE_SUCCESS(rv, rv);
-        }
-        rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
-          "CREATE TABLE moz_hosts_new ("
-            " id INTEGER PRIMARY KEY"
-            ",origin TEXT"
-            ",type TEXT"
-            ",permission INTEGER"
-            ",expireType INTEGER"
-            ",expireTime INTEGER"
-            ",modificationTime INTEGER"
-          ")"));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        nsCOMPtr<mozIStorageStatement> stmt;
-        rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
-          "SELECT host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement "
-          "FROM moz_hosts"), getter_AddRefs(stmt));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        nsCOMPtr<mozIStoragePendingStatement> pending;
-
-        int64_t id = 0;
-        nsAutoCString host, type;
-        uint32_t permission;
-        uint32_t expireType;
-        int64_t expireTime;
-        int64_t modificationTime;
-        uint32_t appId;
-        bool isInBrowserElement;
-        bool hasResult;
-
-        while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
-          // Read in the old row
-          rv = stmt->GetUTF8String(0, host);
-          if (NS_FAILED(rv)) {
-            continue;
-          }
-          rv = stmt->GetUTF8String(1, type);
-          if (NS_FAILED(rv)) {
-            continue;
-          }
-          permission = stmt->AsInt32(2);
-          expireType = stmt->AsInt32(3);
-          expireTime = stmt->AsInt64(4);
-          modificationTime = stmt->AsInt64(5);
-          if (stmt->AsInt64(6) < 0) {
-            continue;
-          }
-          appId = static_cast<uint32_t>(stmt->AsInt64(6));
-          isInBrowserElement = static_cast<bool>(stmt->AsInt32(7));
-
-          UpgradeHostToOriginDBMigration upHelper(mDBConn, &id);
-          rv = UpgradeHostToOriginAndInsert(host, type, permission,
-                                            expireType, expireTime,
-                                            modificationTime, appId,
-                                            isInBrowserElement,
-                                            &upHelper);
-          if (NS_FAILED(rv)) {
-            NS_WARNING("Unexpected failure when upgrading migrating permission from host to origin");
-          }
-        }
-
-        // We rename the old table to moz_hosts_v4 instead of dropping it, such that if
-        // we discover that there was a problem with our migration code in the future, we have information
-        // to roll-back with.
-        rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("ALTER TABLE moz_hosts RENAME TO moz_hosts_v4"));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("ALTER TABLE moz_hosts_new RENAME TO moz_hosts"));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-
     // current version.
     case HOSTS_SCHEMA_VERSION:
       break;
 
     // downgrading.
     // if columns have been added to the table, we can still use the ones we
     // understand safely. if columns have been deleted or altered, just
     // blow away the table and start from scratch! if you change the way
     // a column is interpreted, make sure you also change its name so this
     // check will catch it.
     default:
       {
         // check if all the expected columns exist
         nsCOMPtr<mozIStorageStatement> stmt;
         rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
-          "SELECT origin, type, permission, expireType, expireTime, modificationTime FROM moz_hosts"),
+          "SELECT host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement FROM moz_hosts"),
           getter_AddRefs(stmt));
         if (NS_SUCCEEDED(rv))
           break;
 
         // our columns aren't there - drop the table!
         rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_hosts"));
         NS_ENSURE_SUCCESS(rv, rv);
 
@@ -945,18 +644,18 @@ nsPermissionManager::InitDB(bool aRemove
       }
       break;
     }
   }
 
   // cache frequently used statements (for insertion, deletion, and updating)
   rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
     "INSERT INTO moz_hosts "
-    "(id, origin, type, permission, expireType, expireTime, modificationTime) "
-    "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"), getter_AddRefs(mStmtInsert));
+    "(id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) "
+    "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)"), getter_AddRefs(mStmtInsert));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
     "DELETE FROM moz_hosts "
     "WHERE id = ?1"), getter_AddRefs(mStmtDelete));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
@@ -983,22 +682,24 @@ nsPermissionManager::CreateTable()
   if (NS_FAILED(rv)) return rv;
 
   // create the table
   // SQL also lives in automation.py.in. If you change this SQL change that
   // one too.
   return mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE moz_hosts ("
       " id INTEGER PRIMARY KEY"
-      ",origin TEXT"
+      ",host TEXT"
       ",type TEXT"
       ",permission INTEGER"
       ",expireType INTEGER"
       ",expireTime INTEGER"
       ",modificationTime INTEGER"
+      ",appId INTEGER"
+      ",isInBrowserElement INTEGER"
     ")"));
 }
 
 NS_IMETHODIMP
 nsPermissionManager::Add(nsIURI     *aURI,
                          const char *aType,
                          uint32_t    aPermission,
                          uint32_t    aExpireType,
@@ -1035,25 +736,16 @@ nsPermissionManager::AddFromPrincipal(ns
   }
 
   // We don't add the system principal because it actually has no URI and we
   // always allow action for them.
   if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
     return NS_OK;
   }
 
-  // Null principals can't meaningfully have persisted permissions attached to
-  // them, so we don't allow adding permissions for them.
-  bool isNullPrincipal;
-  nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrincipal);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (isNullPrincipal) {
-    return NS_OK;
-  }
-
   // Permissions may not be added to expanded principals.
   if (IsExpandedPrincipal(aPrincipal)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // A modificationTime of zero will cause AddInternal to use now().
   int64_t modificationTime = 0;
 
@@ -1068,23 +760,31 @@ nsPermissionManager::AddInternal(nsIPrin
                                  int64_t               aID,
                                  uint32_t              aExpireType,
                                  int64_t               aExpireTime,
                                  int64_t               aModificationTime,
                                  NotifyOperationType   aNotifyOperation,
                                  DBOperationType       aDBOperation,
                                  const bool            aIgnoreSessionPermissions)
 {
-  nsAutoCString origin;
-  nsresult rv = aPrincipal->GetOrigin(origin);
+  nsAutoCString host;
+  nsresult rv = GetHostForPrincipal(aPrincipal, host);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!IsChildProcess()) {
-    IPC::Permission permission(origin, aType, aPermission,
-                               aExpireType, aExpireTime);
+    uint32_t appId;
+    rv = aPrincipal->GetAppId(&appId);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    bool isInBrowserElement;
+    rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    IPC::Permission permission(host, appId, isInBrowserElement, aType,
+                               aPermission, aExpireType, aExpireTime);
 
     nsTArray<ContentParent*> cplist;
     ContentParent::GetAll(cplist);
     for (uint32_t i = 0; i < cplist.Length(); ++i) {
       ContentParent* cp = cplist[i];
       // On platforms where we use a preallocated template process we don't
       // want to notify this process about session specific permissions so
       // new tabs or apps created on it won't inherit the session permissions.
@@ -1186,21 +886,31 @@ nsPermissionManager::AddInternal(nsIPrin
         aExpireType = nsIPermissionManager::EXPIRE_NEVER;
       }
 
       entry->GetPermissions().AppendElement(PermissionEntry(id, typeIndex, aPermission,
                                                             aExpireType, aExpireTime,
                                                             aModificationTime));
 
       if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION) {
-        UpdateDB(op, mStmtInsert, id, origin, aType, aPermission, aExpireType, aExpireTime, aModificationTime);
+        uint32_t appId;
+        rv = aPrincipal->GetAppId(&appId);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        bool isInBrowserElement;
+        rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        UpdateDB(op, mStmtInsert, id, host, aType, aPermission, aExpireType, aExpireTime, aModificationTime, appId, isInBrowserElement);
       }
 
       if (aNotifyOperation == eNotify) {
-        NotifyObserversWithPermission(aPrincipal,
+        NotifyObserversWithPermission(host,
+                                      entry->GetKey()->mAppId,
+                                      entry->GetKey()->mIsInBrowserElement,
                                       mTypeArray[typeIndex],
                                       aPermission,
                                       aExpireType,
                                       aExpireTime,
                                       MOZ_UTF16("added"));
       }
 
       break;
@@ -1211,20 +921,22 @@ nsPermissionManager::AddInternal(nsIPrin
       PermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
       id = oldPermissionEntry.mID;
       entry->GetPermissions().RemoveElementAt(index);
 
       if (aDBOperation == eWriteToDB)
         // We care only about the id here so we pass dummy values for all other
         // parameters.
         UpdateDB(op, mStmtDelete, id, EmptyCString(), EmptyCString(), 0,
-                 nsIPermissionManager::EXPIRE_NEVER, 0, 0);
+                 nsIPermissionManager::EXPIRE_NEVER, 0, 0, 0, false);
 
       if (aNotifyOperation == eNotify) {
-        NotifyObserversWithPermission(aPrincipal,
+        NotifyObserversWithPermission(host,
+                                      entry->GetKey()->mAppId,
+                                      entry->GetKey()->mIsInBrowserElement,
                                       mTypeArray[typeIndex],
                                       oldPermissionEntry.mPermission,
                                       oldPermissionEntry.mExpireType,
                                       oldPermissionEntry.mExpireTime,
                                       MOZ_UTF16("deleted"));
       }
 
       // If there are no more permissions stored for that entry, clear it.
@@ -1257,20 +969,22 @@ nsPermissionManager::AddInternal(nsIPrin
       entry->GetPermissions()[index].mExpireType = aExpireType;
       entry->GetPermissions()[index].mExpireTime = aExpireTime;
       entry->GetPermissions()[index].mModificationTime = aModificationTime;
 
       if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION)
         // We care only about the id, the permission and expireType/expireTime/modificationTime here.
         // We pass dummy values for all other parameters.
         UpdateDB(op, mStmtUpdate, id, EmptyCString(), EmptyCString(),
-                 aPermission, aExpireType, aExpireTime, aModificationTime);
+                 aPermission, aExpireType, aExpireTime, aModificationTime, 0, false);
 
       if (aNotifyOperation == eNotify) {
-        NotifyObserversWithPermission(aPrincipal,
+        NotifyObserversWithPermission(host,
+                                      entry->GetKey()->mAppId,
+                                      entry->GetKey()->mIsInBrowserElement,
                                       mTypeArray[typeIndex],
                                       aPermission,
                                       aExpireType,
                                       aExpireTime,
                                       MOZ_UTF16("changed"));
       }
 
       break;
@@ -1311,22 +1025,24 @@ nsPermissionManager::AddInternal(nsIPrin
         uint32_t appId;
         rv = aPrincipal->GetAppId(&appId);
         NS_ENSURE_SUCCESS(rv, rv);
 
         bool isInBrowserElement;
         rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
         NS_ENSURE_SUCCESS(rv, rv);
 
-        UpdateDB(eOperationAdding, mStmtInsert, id, origin, aType, aPermission,
-                 aExpireType, aExpireTime, aModificationTime);
+        UpdateDB(eOperationAdding, mStmtInsert, id, host, aType, aPermission,
+                 aExpireType, aExpireTime, aModificationTime, appId, isInBrowserElement);
       }
 
       if (aNotifyOperation == eNotify) {
-        NotifyObserversWithPermission(aPrincipal,
+        NotifyObserversWithPermission(host,
+                                      entry->GetKey()->mAppId,
+                                      entry->GetKey()->mIsInBrowserElement,
                                       mTypeArray[typeIndex],
                                       aPermission,
                                       aExpireType,
                                       aExpireTime,
                                       MOZ_UTF16("changed"));
       }
 
     }
@@ -1377,18 +1093,22 @@ nsPermissionManager::RemoveFromPrincipal
                      0,
                      eNotify,
                      eWriteToDB);
 }
 
 NS_IMETHODIMP
 nsPermissionManager::RemovePermission(nsIPermission* aPerm)
 {
+  nsAutoCString host;
+  nsresult rv = aPerm->GetHost(host);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   nsCOMPtr<nsIPrincipal> principal;
-  nsresult rv = aPerm->GetPrincipal(getter_AddRefs(principal));
+  rv = GetPrincipal(host, getter_AddRefs(principal));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString type;
   rv = aPerm->GetType(type);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Permissions are uniquely identified by their principal and type.
   // We remove the permission using these two pieces of data.
@@ -1545,39 +1265,50 @@ nsPermissionManager::GetPermissionObject
     return NS_OK;
   }
 
   // Querying the permission object of an nsEP is non-sensical.
   if (IsExpandedPrincipal(aPrincipal)) {
     return NS_ERROR_INVALID_ARG;
   }
 
+  nsAutoCString host;
+  nsresult rv = GetHostForPrincipal(aPrincipal, host);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   int32_t typeIndex = GetTypeIndex(aType, false);
   // If type == -1, the type isn't known,
   // so just return NS_OK
   if (typeIndex == -1) return NS_OK;
 
-  PermissionHashKey* entry = GetPermissionHashKey(aPrincipal, typeIndex, aExactHostMatch);
+  uint32_t appId;
+  rv = aPrincipal->GetAppId(&appId);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool isInBrowserElement;
+  rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PermissionHashKey* entry = GetPermissionHashKey(host, appId, isInBrowserElement,
+                                                  typeIndex, aExactHostMatch);
   if (!entry) {
     return NS_OK;
   }
 
   // We don't call GetPermission(typeIndex) because that returns a fake
   // UNKNOWN_ACTION entry if there is no match.
   int32_t idx = entry->GetPermissionIndex(typeIndex);
   if (-1 == idx) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIPrincipal> principal;
-  nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal));
-  NS_ENSURE_SUCCESS(rv, rv);
-
   PermissionEntry& perm = entry->GetPermissions()[idx];
-  nsCOMPtr<nsIPermission> r = new nsPermission(principal,
+  nsCOMPtr<nsIPermission> r = new nsPermission(entry->GetKey()->mHost,
+                                               entry->GetKey()->mAppId,
+                                               entry->GetKey()->mIsInBrowserElement,
                                                mTypeArray.ElementAt(perm.mType),
                                                perm.mPermission,
                                                perm.mExpireType,
                                                perm.mExpireTime);
   r.forget(aResult);
   return NS_OK;
 }
 
@@ -1619,22 +1350,35 @@ nsPermissionManager::CommonTestPermissio
         // Store it, but keep going to see if we can do better.
         *aPermission = perm;
       }
     }
 
     return NS_OK;
   }
 
+  nsAutoCString host;
+  nsresult rv = GetHostForPrincipal(aPrincipal, host);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   int32_t typeIndex = GetTypeIndex(aType, false);
   // If type == -1, the type isn't known,
   // so just return NS_OK
   if (typeIndex == -1) return NS_OK;
 
-  PermissionHashKey* entry = GetPermissionHashKey(aPrincipal, typeIndex, aExactHostMatch);
+  uint32_t appId;
+  rv = aPrincipal->GetAppId(&appId);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool isInBrowserElement;
+  rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PermissionHashKey* entry = GetPermissionHashKey(host, appId, isInBrowserElement,
+                                                  typeIndex, aExactHostMatch);
   if (!entry ||
       (!aIncludingSession &&
        entry->GetPermission(typeIndex).mNonSessionExpireType ==
          nsIPermissionManager::EXPIRE_SESSION)) {
     return NS_OK;
   }
 
   *aPermission = aIncludingSession
@@ -1646,81 +1390,70 @@ nsPermissionManager::CommonTestPermissio
 
 // Returns PermissionHashKey for a given { host, appId, isInBrowserElement } tuple.
 // This is not simply using PermissionKey because we will walk-up domains in
 // case of |host| contains sub-domains.
 // Returns null if nothing found.
 // Also accepts host on the format "<foo>". This will perform an exact match
 // lookup as the string doesn't contain any dots.
 nsPermissionManager::PermissionHashKey*
-nsPermissionManager::GetPermissionHashKey(nsIPrincipal* aPrincipal,
+nsPermissionManager::GetPermissionHashKey(const nsACString& aHost,
+                                          uint32_t aAppId,
+                                          bool aIsInBrowserElement,
                                           uint32_t aType,
                                           bool aExactHostMatch)
 {
   PermissionHashKey* entry = nullptr;
 
-  nsRefPtr<PermissionKey> key = new PermissionKey(aPrincipal);
+  nsRefPtr<PermissionKey> key = new PermissionKey(aHost, aAppId, aIsInBrowserElement);
   entry = mPermissionTable.GetEntry(key);
 
   if (entry) {
     PermissionEntry permEntry = entry->GetPermission(aType);
 
     // if the entry is expired, remove and keep looking for others.
     // Note that EXPIRE_SESSION only honors expireTime if it is nonzero.
     if ((permEntry.mExpireType == nsIPermissionManager::EXPIRE_TIME ||
          (permEntry.mExpireType == nsIPermissionManager::EXPIRE_SESSION &&
           permEntry.mExpireTime != 0)) &&
         permEntry.mExpireTime <= (PR_Now() / 1000)) {
+      nsCOMPtr<nsIPrincipal> principal;
+      if (NS_FAILED(GetPrincipal(aHost, aAppId, aIsInBrowserElement, getter_AddRefs(principal)))) {
+        return nullptr;
+      }
+
       entry = nullptr;
-      RemoveFromPrincipal(aPrincipal, mTypeArray[aType].get());
+      RemoveFromPrincipal(principal, mTypeArray[aType].get());
     } else if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
       entry = nullptr;
     }
   }
 
   if (entry) {
     return entry;
   }
 
-  // If aExactHostMatch wasn't true, we can check if the base domain has a permission entry.
-  if (!aExactHostMatch) {
-    nsCOMPtr<nsIURI> uri;
-    nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
-    if (NS_FAILED(rv)) {
-      return nullptr;
-    }
+  // If we haven't found an entry, depending on the host, we could try a bit
+  // harder.
+  // If this is a file:// URI, we can check for the presence of the magic entry
+  // <file> which gives permission to all file://. This hack might disappear,
+  // see bug 817007. Note that we don't require aExactHostMatch to be true for
+  // that to keep retro-compatibility.
+  // If this is not a file:// URI, and that aExactHostMatch wasn't true, we can
+  // check if the base domain has a permission entry.
 
-    nsAutoCString host;
-    rv = uri->GetHost(host);
-    if (NS_FAILED(rv)) {
-      return nullptr;
-    }
+  if (StringBeginsWith(aHost, NS_LITERAL_CSTRING("file://"))) {
+    return GetPermissionHashKey(NS_LITERAL_CSTRING("<file>"), aAppId, aIsInBrowserElement, aType, true);
+  }
 
-    nsCString domain = GetNextSubDomainForHost(host);
-    if (domain.IsEmpty()) {
-      return nullptr;
+  if (!aExactHostMatch) {
+    nsCString domain = GetNextSubDomainForHost(aHost);
+    if (!domain.IsEmpty()) {
+      return GetPermissionHashKey(domain, aAppId, aIsInBrowserElement, aType, aExactHostMatch);
     }
-
-    // Create a new principal which is identical to the current one, but with the new host
-    nsCOMPtr<nsIURI> newURI;
-    rv = uri->Clone(getter_AddRefs(newURI));
-    if (NS_FAILED(rv)) {
-      return nullptr;
-    }
-
-    rv = newURI->SetHost(domain);
-    if (NS_FAILED(rv)) {
-      return nullptr;
-    }
-
-    // Copy the attributes over
-    mozilla::OriginAttributes attrs = mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
-    nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(newURI, attrs);
-
-    return GetPermissionHashKey(principal, aType, aExactHostMatch);
   }
 
   // No entry, really...
   return nullptr;
 }
 
 // helper struct for passing arguments into hash enumeration callback.
 struct nsGetEnumeratorData
@@ -1747,20 +1480,19 @@ AddPermissionsToList(nsPermissionManager
 
     // given how "default" permissions work and the possibility of them being
     // overridden with UNKNOWN_ACTION, we might see this value here - but we
     // do *not* want to return them via the enumerator.
     if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
       continue;
     }
 
-    nsCOMPtr<nsIPrincipal> principal;
-    GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal));
-
-    nsPermission *perm = new nsPermission(principal,
+    nsPermission *perm = new nsPermission(entry->GetKey()->mHost,
+                                          entry->GetKey()->mAppId,
+                                          entry->GetKey()->mIsInBrowserElement,
                                           data->types->ElementAt(permEntry.mType),
                                           permEntry.mPermission,
                                           permEntry.mExpireType,
                                           permEntry.mExpireTime);
 
     data->array->AppendObject(perm);
   }
 
@@ -1805,20 +1537,19 @@ AddPermissionsModifiedSinceToList(
 
   for (size_t i = 0; i < entry->GetPermissions().Length(); ++i) {
     const nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i];
 
     if (data->since > permEntry.mModificationTime) {
       continue;
     }
 
-    nsCOMPtr<nsIPrincipal> principal;
-    GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal));
-
-    nsPermission* perm = new nsPermission(principal,
+    nsPermission* perm = new nsPermission(entry->GetKey()->mHost,
+                                          entry->GetKey()->mAppId,
+                                          entry->GetKey()->mIsInBrowserElement,
                                           data->types->ElementAt(permEntry.mType),
                                           permEntry.mPermission,
                                           permEntry.mExpireType,
                                           permEntry.mExpireTime);
 
     data->array->AppendObject(perm);
   }
   return PL_DHASH_NEXT;
@@ -1831,31 +1562,32 @@ nsPermissionManager::RemoveAllModifiedSi
 
   // roll an nsCOMArray of all our permissions, then hand out an enumerator
   nsCOMArray<nsIPermission> array;
   nsGetEnumeratorData data(&array, &mTypeArray, aModificationTime);
 
   mPermissionTable.EnumerateEntries(AddPermissionsModifiedSinceToList, &data);
 
   for (int32_t i = 0; i<array.Count(); ++i) {
-    nsCOMPtr<nsIPrincipal> principal;
+    nsAutoCString host;
+    bool isInBrowserElement = false;
     nsAutoCString type;
+    uint32_t appId = 0;
 
-    nsresult rv = array[i]->GetPrincipal(getter_AddRefs(principal));
-    if (NS_FAILED(rv)) {
+    array[i]->GetHost(host);
+    array[i]->GetIsInBrowserElement(&isInBrowserElement);
+    array[i]->GetType(type);
+    array[i]->GetAppId(&appId);
+
+    nsCOMPtr<nsIPrincipal> principal;
+    if (NS_FAILED(GetPrincipal(host, appId, isInBrowserElement,
+                               getter_AddRefs(principal)))) {
       NS_ERROR("GetPrincipal() failed!");
       continue;
     }
-
-    rv = array[i]->GetType(type);
-    if (NS_FAILED(rv)) {
-      NS_ERROR("GetType() failed!");
-      continue;
-    }
-
     // AddInternal handles removal, so let it do the work...
     AddInternal(
       principal,
       type,
       nsIPermissionManager::UNKNOWN_ACTION,
       0,
       nsIPermissionManager::EXPIRE_NEVER, 0, 0,
       nsPermissionManager::eNotify,
@@ -1870,116 +1602,136 @@ nsPermissionManager::RemoveAllModifiedSi
 PLDHashOperator
 nsPermissionManager::GetPermissionsForApp(nsPermissionManager::PermissionHashKey* entry, void* arg)
 {
   GetPermissionsForAppStruct* data = static_cast<GetPermissionsForAppStruct*>(arg);
 
   for (uint32_t i = 0; i < entry->GetPermissions().Length(); ++i) {
     nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i];
 
-    nsCOMPtr<nsIPrincipal> principal;
-    GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal));
-
-    uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
-    principal->GetAppId(&appId);
-
-    bool isInBrowserElement;
-    principal->GetIsInBrowserElement(&isInBrowserElement);
-
-    if (appId != data->appId ||
-        (data->browserOnly && !isInBrowserElement)) {
+    if (entry->GetKey()->mAppId != data->appId ||
+        (data->browserOnly && !entry->GetKey()->mIsInBrowserElement)) {
       continue;
     }
 
-    data->permissions.AppendObject(new nsPermission(principal,
+    data->permissions.AppendObject(new nsPermission(entry->GetKey()->mHost,
+                                                    entry->GetKey()->mAppId,
+                                                    entry->GetKey()->mIsInBrowserElement,
                                                     gPermissionManager->mTypeArray.ElementAt(permEntry.mType),
                                                     permEntry.mPermission,
                                                     permEntry.mExpireType,
                                                     permEntry.mExpireTime));
   }
 
   return PL_DHASH_NEXT;
 }
 
 NS_IMETHODIMP
 nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId, bool aBrowserOnly)
 {
   ENSURE_NOT_CHILD_PROCESS;
   NS_ENSURE_ARG(aAppId != nsIScriptSecurityManager::NO_APP_ID);
 
+  // We begin by removing all the permissions from the DB.
+  // After clearing the DB, we call AddInternal() to make sure that all
+  // processes are aware of this change and the representation of the DB in
+  // memory is updated.
   // We have to get all permissions associated with an application and then
   // remove those because doing so in EnumerateEntries() would fail because
   // we might happen to actually delete entries from the list.
 
+  nsAutoCString sql;
+  sql.AppendLiteral("DELETE FROM moz_hosts WHERE appId=");
+  sql.AppendInt(aAppId);
+
+  if (aBrowserOnly) {
+    sql.AppendLiteral(" AND isInBrowserElement=1");
+  }
+
+  nsCOMPtr<mozIStorageAsyncStatement> removeStmt;
+  nsresult rv = mDBConn->CreateAsyncStatement(sql, getter_AddRefs(removeStmt));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<mozIStoragePendingStatement> pending;
+  rv = removeStmt->ExecuteAsync(nullptr, getter_AddRefs(pending));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   GetPermissionsForAppStruct data(aAppId, aBrowserOnly);
   mPermissionTable.EnumerateEntries(GetPermissionsForApp, &data);
 
   for (int32_t i=0; i<data.permissions.Count(); ++i) {
-    nsCOMPtr<nsIPrincipal> principal;
+    nsAutoCString host;
+    bool isInBrowserElement;
     nsAutoCString type;
 
-    data.permissions[i]->GetPrincipal(getter_AddRefs(principal));
+    data.permissions[i]->GetHost(host);
+    data.permissions[i]->GetIsInBrowserElement(&isInBrowserElement);
     data.permissions[i]->GetType(type);
 
+    nsCOMPtr<nsIPrincipal> principal;
+    if (NS_FAILED(GetPrincipal(host, aAppId, isInBrowserElement,
+                               getter_AddRefs(principal)))) {
+      NS_ERROR("GetPrincipal() failed!");
+      continue;
+    }
+
     AddInternal(principal,
                 type,
                 nsIPermissionManager::UNKNOWN_ACTION,
                 0,
                 nsIPermissionManager::EXPIRE_NEVER,
                 0,
                 0,
                 nsPermissionManager::eNotify,
-                nsPermissionManager::eWriteToDB);
+                nsPermissionManager::eNoDBOperation);
   }
 
   return NS_OK;
 }
 
 PLDHashOperator
 nsPermissionManager::RemoveExpiredPermissionsForAppEnumerator(
   nsPermissionManager::PermissionHashKey* entry, void* arg)
 {
-  uint32_t* targetAppId = static_cast<uint32_t*>(arg);
+  uint32_t* appId = static_cast<uint32_t*>(arg);
 
   for (uint32_t i = 0; i < entry->GetPermissions().Length(); ++i) {
-    nsCOMPtr<nsIPrincipal> principal;
-    GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal));
-
-    uint32_t appId;
-    principal->GetAppId(&appId);
-
-    if (appId != *targetAppId) {
+    if (entry->GetKey()->mAppId != *appId) {
       continue;
     }
 
     nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i];
     if (permEntry.mExpireType != nsIPermissionManager::EXPIRE_SESSION) {
       continue;
     }
 
     if (permEntry.mNonSessionExpireType == nsIPermissionManager::EXPIRE_SESSION) {
       PermissionEntry oldPermissionEntry = entry->GetPermissions()[i];
 
       entry->GetPermissions().RemoveElementAt(i);
 
-      gPermissionManager->NotifyObserversWithPermission(principal,
+      gPermissionManager->NotifyObserversWithPermission(entry->GetKey()->mHost,
+                                                        entry->GetKey()->mAppId,
+                                                        entry->GetKey()->mIsInBrowserElement,
                                                         gPermissionManager->mTypeArray.ElementAt(oldPermissionEntry.mType),
                                                         oldPermissionEntry.mPermission,
                                                         oldPermissionEntry.mExpireType,
                                                         oldPermissionEntry.mExpireTime,
                                                         MOZ_UTF16("deleted"));
       --i;
       continue;
     }
 
     permEntry.mPermission = permEntry.mNonSessionPermission;
     permEntry.mExpireType = permEntry.mNonSessionExpireType;
     permEntry.mExpireTime = permEntry.mNonSessionExpireTime;
 
-    gPermissionManager->NotifyObserversWithPermission(principal,
+    gPermissionManager->NotifyObserversWithPermission(entry->GetKey()->mHost,
+                                                      entry->GetKey()->mAppId,
+                                                      entry->GetKey()->mIsInBrowserElement,
                                                       gPermissionManager->mTypeArray.ElementAt(permEntry.mType),
                                                       permEntry.mPermission,
                                                       permEntry.mExpireType,
                                                       permEntry.mExpireTime,
                                                       MOZ_UTF16("changed"));
   }
 
   return PL_DHASH_NEXT;
@@ -2033,25 +1785,27 @@ nsPermissionManager::GetTypeIndex(const 
 
   elem->Assign(aType);
   return mTypeArray.Length() - 1;
 }
 
 // wrapper function for mangling (host,type,perm,expireType,expireTime)
 // set into an nsIPermission.
 void
-nsPermissionManager::NotifyObserversWithPermission(nsIPrincipal*     aPrincipal,
+nsPermissionManager::NotifyObserversWithPermission(const nsACString &aHost,
+                                                   uint32_t          aAppId,
+                                                   bool              aIsInBrowserElement,
                                                    const nsCString  &aType,
                                                    uint32_t          aPermission,
                                                    uint32_t          aExpireType,
                                                    int64_t           aExpireTime,
                                                    const char16_t  *aData)
 {
   nsCOMPtr<nsIPermission> permission =
-    new nsPermission(aPrincipal, aType, aPermission,
+    new nsPermission(aHost, aAppId, aIsInBrowserElement, aType, aPermission,
                      aExpireType, aExpireTime);
   if (permission)
     NotifyObservers(permission, aData);
 }
 
 // notify observers that the permission list changed. there are four possible
 // values for aData:
 // "deleted" means a permission was deleted. aPermission is the deleted permission.
@@ -2092,37 +1846,39 @@ nsPermissionManager::Read()
 
     bool hasResult;
     rv = stmtDeleteExpired->ExecuteStep(&hasResult);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<mozIStorageStatement> stmt;
   rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
-    "SELECT id, origin, type, permission, expireType, expireTime, modificationTime "
+    "SELECT id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement "
     "FROM moz_hosts"), getter_AddRefs(stmt));
   NS_ENSURE_SUCCESS(rv, rv);
 
   int64_t id;
-  nsAutoCString origin, type;
+  nsAutoCString host, type;
   uint32_t permission;
   uint32_t expireType;
   int64_t expireTime;
   int64_t modificationTime;
+  uint32_t appId;
+  bool isInBrowserElement;
   bool hasResult;
   bool readError = false;
 
   while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
     // explicitly set our entry id counter for use in AddInternal(),
     // and keep track of the largest id so we know where to pick up.
     id = stmt->AsInt64(0);
     if (id > mLargestID)
       mLargestID = id;
 
-    rv = stmt->GetUTF8String(1, origin);
+    rv = stmt->GetUTF8String(1, host);
     if (NS_FAILED(rv)) {
       readError = true;
       continue;
     }
 
     rv = stmt->GetUTF8String(2, type);
     if (NS_FAILED(rv)) {
       readError = true;
@@ -2131,18 +1887,26 @@ nsPermissionManager::Read()
 
     permission = stmt->AsInt32(3);
     expireType = stmt->AsInt32(4);
 
     // convert into int64_t values (milliseconds)
     expireTime = stmt->AsInt64(5);
     modificationTime = stmt->AsInt64(6);
 
+    if (stmt->AsInt64(7) < 0) {
+      readError = true;
+      continue;
+    }
+
+    appId = static_cast<uint32_t>(stmt->AsInt64(7));
+    isInBrowserElement = static_cast<bool>(stmt->AsInt32(8));
+
     nsCOMPtr<nsIPrincipal> principal;
-    nsresult rv = GetPrincipalFromOrigin(origin, getter_AddRefs(principal));
+    nsresult rv = GetPrincipal(host, appId, isInBrowserElement, getter_AddRefs(principal));
     if (NS_FAILED(rv)) {
       readError = true;
       continue;
     }
 
     rv = AddInternal(principal, type, permission, id, expireType, expireTime,
                      modificationTime, eDontNotify, eNoDBOperation);
     if (NS_FAILED(rv)) {
@@ -2155,17 +1919,16 @@ nsPermissionManager::Read()
     NS_ERROR("Error occured while reading the permissions database!");
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 static const char kMatchTypeHost[] = "host";
-static const char kMatchTypeOrigin[] = "origin";
 
 // Import() will read a file from the profile directory and add them to the
 // database before deleting the file - ie, this is a one-shot operation that
 // will not succeed on subsequent runs as the file imported from is removed.
 nsresult
 nsPermissionManager::Import()
 {
   nsresult rv;
@@ -2265,58 +2028,42 @@ nsPermissionManager::_DoImport(nsIInputS
 
     nsTArray<nsCString> lineArray;
 
     // Split the line at tabs
     ParseString(line, '\t', lineArray);
 
     if (lineArray[0].EqualsLiteral(kMatchTypeHost) &&
         lineArray.Length() == 4) {
-      nsresult error = NS_OK;
+
+      nsresult error;
       uint32_t permission = lineArray[2].ToInteger(&error);
       if (NS_FAILED(error))
         continue;
 
+      // hosts might be encoded in UTF8; switch them to ACE to be consistent
+      if (!IsASCII(lineArray[3])) {
+        rv = NormalizeToACE(lineArray[3]);
+        if (NS_FAILED(rv))
+          continue;
+      }
+
+      nsCOMPtr<nsIPrincipal> principal;
+      nsresult rv = GetPrincipal(lineArray[3], getter_AddRefs(principal));
+      NS_ENSURE_SUCCESS(rv, rv);
+
       // the import file format doesn't handle modification times, so we use
       // 0, which AddInternal will convert to now()
       int64_t modificationTime = 0;
 
-      UpgradeHostToOriginHostfileImport upHelper(this, operation, id);
-      error = UpgradeHostToOriginAndInsert(lineArray[3], lineArray[1], permission,
-                                           nsIPermissionManager::EXPIRE_NEVER, 0,
-                                           modificationTime, nsIScriptSecurityManager::NO_APP_ID,
-                                           false, &upHelper);
-      if (NS_FAILED(error)) {
-        NS_WARNING("There was a problem importing a host permission");
-      }
-    } else if (lineArray[0].EqualsLiteral(kMatchTypeOrigin) &&
-               lineArray.Length() == 4) {
-      nsresult error = NS_OK;
-      uint32_t permission = lineArray[2].ToInteger(&error);
-      if (NS_FAILED(error))
-        continue;
-
-      nsCOMPtr<nsIPrincipal> principal;
-      error = GetPrincipalFromOrigin(lineArray[3], getter_AddRefs(principal));
-      if (NS_FAILED(error)) {
-        NS_WARNING("Couldn't import an origin permission - malformed origin");
-        continue;
-      }
-
-      // the import file format doesn't handle modification times, so we use
-      // 0, which AddInternal will convert to now()
-      int64_t modificationTime = 0;
-
-      error = AddInternal(principal, lineArray[1], permission, id,
-                          nsIPermissionManager::EXPIRE_NEVER, 0,
-                          modificationTime,
-                          eDontNotify, operation);
-      if (NS_FAILED(error)) {
-        NS_WARNING("There was a problem importing an origin permission");
-      }
+      rv = AddInternal(principal, lineArray[1], permission, id,
+                       nsIPermissionManager::EXPIRE_NEVER, 0,
+                       modificationTime,
+                       eDontNotify, operation);
+      NS_ENSURE_SUCCESS(rv, rv);
     }
 
   } while (isMore);
 
   return NS_OK;
 }
 
 nsresult
@@ -2331,53 +2078,61 @@ nsPermissionManager::NormalizeToACE(nsCS
 
   return mIDNService->ConvertUTF8toACE(aHost, aHost);
 }
 
 void
 nsPermissionManager::UpdateDB(OperationType aOp,
                               mozIStorageAsyncStatement* aStmt,
                               int64_t aID,
-                              const nsACString &aOrigin,
+                              const nsACString &aHost,
                               const nsACString &aType,
                               uint32_t aPermission,
                               uint32_t aExpireType,
                               int64_t aExpireTime,
-                              int64_t aModificationTime)
+                              int64_t aModificationTime,
+                              uint32_t aAppId,
+                              bool aIsInBrowserElement)
 {
   ENSURE_NOT_CHILD_PROCESS_NORET;
 
   nsresult rv;
 
   // no statement is ok - just means we don't have a profile
   if (!aStmt)
     return;
 
   switch (aOp) {
   case eOperationAdding:
     {
       rv = aStmt->BindInt64ByIndex(0, aID);
       if (NS_FAILED(rv)) break;
 
-      rv = aStmt->BindUTF8StringByIndex(1, aOrigin);
+      rv = aStmt->BindUTF8StringByIndex(1, aHost);
       if (NS_FAILED(rv)) break;
 
       rv = aStmt->BindUTF8StringByIndex(2, aType);
       if (NS_FAILED(rv)) break;
 
       rv = aStmt->BindInt32ByIndex(3, aPermission);
       if (NS_FAILED(rv)) break;
 
       rv = aStmt->BindInt32ByIndex(4, aExpireType);
       if (NS_FAILED(rv)) break;
 
       rv = aStmt->BindInt64ByIndex(5, aExpireTime);
       if (NS_FAILED(rv)) break;
 
       rv = aStmt->BindInt64ByIndex(6, aModificationTime);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt64ByIndex(7, aAppId);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt64ByIndex(8, aIsInBrowserElement);
       break;
     }
 
   case eOperationRemoving:
     {
       rv = aStmt->BindInt64ByIndex(0, aID);
       break;
     }
@@ -2486,22 +2241,35 @@ nsPermissionManager::UpdateExpireTime(ns
     return NS_OK;
   }
 
   // Setting the expire time of an nsEP is non-sensical.
   if (IsExpandedPrincipal(aPrincipal)) {
     return NS_ERROR_INVALID_ARG;
   }
 
+  nsAutoCString host;
+  nsresult rv = GetHostForPrincipal(aPrincipal, host);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   int32_t typeIndex = GetTypeIndex(aType, false);
   // If type == -1, the type isn't known,
   // so just return NS_OK
   if (typeIndex == -1) return NS_OK;
 
-  PermissionHashKey* entry = GetPermissionHashKey(aPrincipal, typeIndex, aExactHostMatch);
+  uint32_t appId;
+  rv = aPrincipal->GetAppId(&appId);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool isInBrowserElement;
+  rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PermissionHashKey* entry = GetPermissionHashKey(host, appId, isInBrowserElement,
+                                                  typeIndex, aExactHostMatch);
   if (!entry) {
     return NS_OK;
   }
 
   int32_t idx = entry->GetPermissionIndex(typeIndex);
   if (-1 == idx) {
     return NS_OK;
   }
@@ -2521,17 +2289,18 @@ nsPermissionManager::FetchPermissions() 
   // Get the permissions from the parent process
   InfallibleTArray<IPC::Permission> perms;
   ChildProcess()->SendReadPermissions(&perms);
 
   for (uint32_t i = 0; i < perms.Length(); i++) {
     const IPC::Permission &perm = perms[i];
 
     nsCOMPtr<nsIPrincipal> principal;
-    nsresult rv = GetPrincipalFromOrigin(perm.origin, getter_AddRefs(principal));
+    nsresult rv = GetPrincipal(perm.host, perm.appId,
+                               perm.isInBrowserElement, getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // The child process doesn't care about modification times - it neither
     // reads nor writes, nor removes them based on the date - so 0 (which
     // will end up as now()) is fine.
     uint64_t modificationTime = 0;
     AddInternal(principal, perm.type, perm.capability, 0, perm.expireType,
                 perm.expireTime, modificationTime, eNotify, eNoDBOperation,
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -66,32 +66,45 @@ public:
    *
    * NOTE: It could be implementing nsIHashable but there is no reason to worry
    * with XPCOM interfaces while we don't need to.
    */
   class PermissionKey
   {
   public:
     explicit PermissionKey(nsIPrincipal* aPrincipal);
-    explicit PermissionKey(const nsACString& aOrigin)
-      : mOrigin(aOrigin)
+    PermissionKey(const nsACString& aHost,
+                  uint32_t aAppId,
+                  bool aIsInBrowserElement)
+      : mHost(aHost)
+      , mAppId(aAppId)
+      , mIsInBrowserElement(aIsInBrowserElement)
     {
     }
 
     bool operator==(const PermissionKey& aKey) const {
-      return mOrigin.Equals(aKey.mOrigin);
+      return mHost.Equals(aKey.mHost) &&
+             mAppId == aKey.mAppId &&
+             mIsInBrowserElement == aKey.mIsInBrowserElement;
     }
 
     PLDHashNumber GetHashCode() const {
-      return mozilla::HashString(mOrigin);
+      nsAutoCString str;
+      str.Assign(mHost);
+      str.AppendInt(mAppId);
+      str.AppendInt(static_cast<int32_t>(mIsInBrowserElement));
+
+      return mozilla::HashString(str);
     }
 
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey)
 
-    nsCString mOrigin;
+    nsCString mHost;
+    uint32_t  mAppId;
+    bool      mIsInBrowserElement;
 
   private:
     // Default ctor shouldn't be used.
     PermissionKey() = delete;
 
     // Dtor shouldn't be used outside of the class.
     ~PermissionKey() {};
   };
@@ -204,34 +217,38 @@ public:
   static void AppClearDataObserverInit();
 
 private:
   virtual ~nsPermissionManager();
 
   int32_t GetTypeIndex(const char *aTypeString,
                        bool        aAdd);
 
-  PermissionHashKey* GetPermissionHashKey(nsIPrincipal* aPrincipal,
-                                          uint32_t      aType,
-                                          bool          aExactHostMatch);
+  PermissionHashKey* GetPermissionHashKey(const nsACString& aHost,
+                                          uint32_t aAppId,
+                                          bool aIsInBrowserElement,
+                                          uint32_t          aType,
+                                          bool              aExactHostMatch);
 
   nsresult CommonTestPermission(nsIPrincipal* aPrincipal,
                                 const char *aType,
                                 uint32_t   *aPermission,
                                 bool        aExactHostMatch,
                                 bool        aIncludingSession);
 
   nsresult OpenDatabase(nsIFile* permissionsFile);
   nsresult InitDB(bool aRemoveFile);
   nsresult CreateTable();
   nsresult Import();
   nsresult ImportDefaults();
   nsresult _DoImport(nsIInputStream *inputStream, mozIStorageConnection *aConn);
   nsresult Read();
-  void     NotifyObserversWithPermission(nsIPrincipal*     aPrincipal,
+  void     NotifyObserversWithPermission(const nsACString &aHost,
+                                         uint32_t          aAppId,
+                                         bool              aIsInBrowserElement,
                                          const nsCString  &aType,
                                          uint32_t          aPermission,
                                          uint32_t          aExpireType,
                                          int64_t           aExpireTime,
                                          const char16_t  *aData);
   void     NotifyObservers(nsIPermission *aPermission, const char16_t *aData);
 
   // Finalize all statements, close the DB and null it.
@@ -239,22 +256,24 @@ private:
   void     CloseDB(bool aRebuildOnSuccess = false);
 
   nsresult RemoveAllInternal(bool aNotifyObservers);
   nsresult RemoveAllFromMemory();
   nsresult NormalizeToACE(nsCString &aHost);
   static void UpdateDB(OperationType aOp,
                        mozIStorageAsyncStatement* aStmt,
                        int64_t aID,
-                       const nsACString& aOrigin,
+                       const nsACString& aHost,
                        const nsACString& aType,
                        uint32_t aPermission,
                        uint32_t aExpireType,
                        int64_t aExpireTime,
-                       int64_t aModificationTime);
+                       int64_t aModificationTime,
+                       uint32_t aAppId,
+                       bool aIsInBrowserElement);
 
   nsresult RemoveExpiredPermissionsForApp(uint32_t aAppId);
 
   /**
    * This struct has to be passed as an argument to GetPermissionsForApp.
    * |appId| and |browserOnly| have to be defined.
    * |permissions| will be filed with permissions that are related to the app.
    * If |browserOnly| is true, only permissions related to a browserElement will
--- a/extensions/cookie/test/test_app_uninstall_permissions.html
+++ b/extensions/cookie/test/test_app_uninstall_permissions.html
@@ -37,17 +37,17 @@ var ioService = Cc["@mozilla.org/network
 // If aAppId = -1, returns permissions count, regardless of app.
 function getPermissionCountForApp(aAppId) {
   var nbPermissions = 0;
   var enumerator = permManager.enumerator;
 
   while (enumerator.hasMoreElements()) {
     var permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
 
-    if (permission.principal.appId == aAppId || aAppId == -1) {
+    if (permission.appId == aAppId || aAppId == -1) {
       nbPermissions++;
     }
   }
 
   return nbPermissions;
 }
 
 permManager.addFromPrincipal(window.document.nodePrincipal, "webapps-manage",
--- a/extensions/cookie/test/unit/test_permmanager_defaults.js
+++ b/extensions/cookie/test/unit/test_permmanager_defaults.js
@@ -1,16 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // The origin we use in most of the tests.
-const TEST_ORIGIN = NetUtil.newURI("http://example.org");
-const TEST_ORIGIN_HTTPS = NetUtil.newURI("https://example.org");
-const TEST_ORIGIN_2 = NetUtil.newURI("http://example.com");
-const TEST_ORIGIN_3 = NetUtil.newURI("https://example2.com:8080");
+const TEST_ORIGIN = "example.org";
+const TEST_ORIGIN_2 = "example.com";
 const TEST_PERMISSION = "test-permission";
 Components.utils.import("resource://gre/modules/Promise.jsm");
 
 function promiseTimeout(delay) {
   let deferred = Promise.defer();
   do_timeout(delay, deferred.resolve);
   return deferred.promise;
 }
@@ -32,66 +30,44 @@ add_task(function* do_test() {
                 createInstance(Ci.nsIFileOutputStream);
   ostream.init(file, -1, 0666, 0);
   let conv = Cc["@mozilla.org/intl/converter-output-stream;1"].
              createInstance(Ci.nsIConverterOutputStream);
   conv.init(ostream, "UTF-8", 0, 0);
 
   conv.writeString("# this is a comment\n");
   conv.writeString("\n"); // a blank line!
-  conv.writeString("host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN.host + "\n");
-  conv.writeString("host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN_2.host + "\n");
-  conv.writeString("origin\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN_3.spec + "\n");
-  conv.writeString("origin\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN.spec + "^appId=1000&inBrowser=1\n");
+  conv.writeString("host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN + "\n");
+  conv.writeString("host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN_2 + "\n");
   ostream.close();
 
   // Set the preference used by the permission manager so the file is read.
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "file://" + file.path);
 
   // initialize the permission manager service - it will read that default.
   let pm = Cc["@mozilla.org/permissionmanager;1"].
            getService(Ci.nsIPermissionManager);
 
   // test the default permission was applied.
-  let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(TEST_ORIGIN);
-  let principalHttps = Services.scriptSecurityManager.getNoAppCodebasePrincipal(TEST_ORIGIN_HTTPS);
-  let principal2 = Services.scriptSecurityManager.getNoAppCodebasePrincipal(TEST_ORIGIN_2);
-  let principal3 = Services.scriptSecurityManager.getNoAppCodebasePrincipal(TEST_ORIGIN_3);
-  let principal4 = Services.scriptSecurityManager.getAppCodebasePrincipal(TEST_ORIGIN, 1000, true);
-  let principal5 = Services.scriptSecurityManager.getAppCodebasePrincipal(TEST_ORIGIN_3, 1000, true);
+  let permURI = NetUtil.newURI("http://" + TEST_ORIGIN);
+  let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(permURI);
 
   do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
               pm.testPermissionFromPrincipal(principal, TEST_PERMISSION));
-  do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
-              pm.testPermissionFromPrincipal(principalHttps, TEST_PERMISSION));
-  do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
-              pm.testPermissionFromPrincipal(principal3, TEST_PERMISSION));
-  do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
-              pm.testPermissionFromPrincipal(principal4, TEST_PERMISSION));
-
-  // Didn't add
-  do_check_eq(Ci.nsIPermissionManager.UNKNOWN_ACTION,
-              pm.testPermissionFromPrincipal(principal5, TEST_PERMISSION));
 
   // the permission should exist in the enumerator.
-  do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION, findCapabilityViaEnum(TEST_ORIGIN));
-  do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION, findCapabilityViaEnum(TEST_ORIGIN_3));
-
+  do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION, findCapabilityViaEnum());
   // but should not have been written to the DB
   yield checkCapabilityViaDB(null);
 
   // remove all should not throw and the default should remain
   pm.removeAll();
 
   do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
               pm.testPermissionFromPrincipal(principal, TEST_PERMISSION));
-  do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
-              pm.testPermissionFromPrincipal(principal3, TEST_PERMISSION));
-  do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
-              pm.testPermissionFromPrincipal(principal4, TEST_PERMISSION));
 
   // Asking for this permission to be removed should result in that permission
   // having UNKNOWN_ACTION
   pm.removeFromPrincipal(principal, TEST_PERMISSION);
   do_check_eq(Ci.nsIPermissionManager.UNKNOWN_ACTION,
               pm.testPermissionFromPrincipal(principal, TEST_PERMISSION));
   // and we should have this UNKNOWN_ACTION reflected in the DB
   yield checkCapabilityViaDB(Ci.nsIPermissionManager.UNKNOWN_ACTION);
@@ -124,16 +100,19 @@ add_task(function* do_test() {
               pm.testPermissionFromPrincipal(principal, TEST_PERMISSION));
   do_check_eq(Ci.nsIPermissionManager.PROMPT_ACTION, findCapabilityViaEnum());
   yield checkCapabilityViaDB(Ci.nsIPermissionManager.PROMPT_ACTION);
 
   // --------------------------------------------------------------
   // check default permissions and removeAllSince work as expected.
   pm.removeAll(); // ensure only defaults are there.
 
+  let permURI2 = NetUtil.newURI("http://" + TEST_ORIGIN_2);
+  let principal2 = Services.scriptSecurityManager.getNoAppCodebasePrincipal(permURI2);
+
   // default for both principals is allow.
   do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
               pm.testPermissionFromPrincipal(principal, TEST_PERMISSION));
   do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
               pm.testPermissionFromPrincipal(principal2, TEST_PERMISSION));
 
   // Add a default override for TEST_ORIGIN_2 - this one should *not* be
   // restored in removeAllSince()
@@ -165,44 +144,44 @@ add_task(function* do_test() {
 
   // remove the temp file we created.
   file.remove(false);
 });
 
 // use an enumerator to find the requested permission.  Returns the permission
 // value (ie, the "capability" in nsIPermission parlance) or null if it can't
 // be found.
-function findCapabilityViaEnum(origin = TEST_ORIGIN, type = TEST_PERMISSION) {
+function findCapabilityViaEnum(host = TEST_ORIGIN, type = TEST_PERMISSION) {
   let result = undefined;
   let e = Services.perms.enumerator;
   while (e.hasMoreElements()) {
     let perm = e.getNext().QueryInterface(Ci.nsIPermission);
-    if (perm.matchesURI(origin, true) &&
+    if (perm.host == host &&
         perm.type == type) {
       if (result !== undefined) {
         // we've already found one previously - that's bad!
         do_throw("enumerator found multiple entries");
       }
       result = perm.capability;
     }
   }
   return result || null;
 }
 
 // A function to check the DB has the specified capability.  As the permission
 // manager uses async DB operations without a completion callback, the
 // distinct possibility exists that our checking of the DB will happen before
 // the permission manager update has completed - so we just retry a few times.
 // Returns a promise.
-function checkCapabilityViaDB(expected, origin = TEST_ORIGIN, type = TEST_PERMISSION) {
+function checkCapabilityViaDB(expected, host = TEST_ORIGIN, type = TEST_PERMISSION) {
   let deferred = Promise.defer();
   let count = 0;
   let max = 20;
   let do_check = () => {
-    let got = findCapabilityViaDB(origin, type);
+    let got = findCapabilityViaDB(host, type);
     if (got == expected) {
       // the do_check_eq() below will succeed - which is what we want.
       do_check_eq(got, expected, "The database has the expected value");
       deferred.resolve();
       return;
     }
     // value isn't correct - see if we've retried enough
     if (count++ == max) {
@@ -216,31 +195,28 @@ function checkCapabilityViaDB(expected, 
   }
   do_check();
   return deferred.promise;
 }
 
 // use the DB to find the requested permission.   Returns the permission
 // value (ie, the "capability" in nsIPermission parlance) or null if it can't
 // be found.
-function findCapabilityViaDB(origin = TEST_ORIGIN, type = TEST_PERMISSION) {
-  let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(origin);
-  let originStr = principal.origin;
-
+function findCapabilityViaDB(host = TEST_ORIGIN, type = TEST_PERMISSION) {
   let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
   file.append("permissions.sqlite");
 
   let storage = Cc["@mozilla.org/storage/service;1"]
                   .getService(Ci.mozIStorageService);
 
   let connection = storage.openDatabase(file);
 
   let query = connection.createStatement(
-      "SELECT permission FROM moz_hosts WHERE origin = :origin AND type = :type");
-  query.bindByName("origin", originStr);
+      "SELECT permission FROM moz_hosts WHERE host = :host AND type = :type");
+  query.bindByName("host", host);
   query.bindByName("type", type);
 
   if (!query.executeStep()) {
     // no row
     return null;
   }
   let result = query.getInt32(0);
   if (query.executeStep()) {
--- a/extensions/cookie/test/unit/test_permmanager_getPermissionObject.js
+++ b/extensions/cookie/test/unit/test_permmanager_getPermissionObject.js
@@ -24,71 +24,71 @@ function run_test() {
   let subSubPrincipal = getPrincipalFromURI("http://sub.sub.example.com");
 
   do_check_null(pm.getPermissionObject(principal, "test/pobject", false));
   do_check_null(pm.getPermissionObject(principal, "test/pobject", true));
 
   pm.addFromPrincipal(principal, "test/pobject", pm.ALLOW_ACTION);
   var rootPerm = pm.getPermissionObject(principal, "test/pobject", false);
   do_check_true(rootPerm != null);
-  do_check_eq(rootPerm.principal.origin, "http://example.com");
+  do_check_eq(rootPerm.host, "example.com");
   do_check_eq(rootPerm.type, "test/pobject");
   do_check_eq(rootPerm.capability, pm.ALLOW_ACTION);
   do_check_eq(rootPerm.expireType, pm.EXPIRE_NEVER);
 
   var rootPerm2 = pm.getPermissionObject(principal, "test/pobject", true);
   do_check_true(rootPerm != null);
-  do_check_eq(rootPerm.principal.origin, "http://example.com");
+  do_check_eq(rootPerm.host, "example.com");
 
   var subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", true);
   do_check_null(subPerm);
   subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", false);
   do_check_true(subPerm != null);
-  do_check_eq(subPerm.principal.origin, "http://example.com");
+  do_check_eq(subPerm.host, "example.com");
   do_check_eq(subPerm.type, "test/pobject");
   do_check_eq(subPerm.capability, pm.ALLOW_ACTION);
 
   subPerm = pm.getPermissionObject(subSubPrincipal, "test/pobject", true);
   do_check_null(subPerm);
   subPerm = pm.getPermissionObject(subSubPrincipal, "test/pobject", false);
   do_check_true(subPerm != null);
-  do_check_eq(subPerm.principal.origin, "http://example.com");
+  do_check_eq(subPerm.host, "example.com");
 
   pm.addFromPrincipal(principal, "test/pobject", pm.DENY_ACTION, pm.EXPIRE_SESSION);
 
   // make sure permission objects are not dynamic
   do_check_eq(rootPerm.capability, pm.ALLOW_ACTION);
 
   // but do update on change
   rootPerm = pm.getPermissionObject(principal, "test/pobject", true);
   do_check_eq(rootPerm.capability, pm.DENY_ACTION);
   do_check_eq(rootPerm.expireType, pm.EXPIRE_SESSION);
 
   subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", false);
-  do_check_eq(subPerm.principal.origin, "http://example.com");
+  do_check_eq(subPerm.host, "example.com");
   do_check_eq(subPerm.capability, pm.DENY_ACTION);
   do_check_eq(subPerm.expireType, pm.EXPIRE_SESSION);
 
   pm.addFromPrincipal(subPrincipal, "test/pobject", pm.PROMPT_ACTION);
   rootPerm = pm.getPermissionObject(principal, "test/pobject", true);
-  do_check_eq(rootPerm.principal.origin, "http://example.com");
+  do_check_eq(rootPerm.host, "example.com");
   do_check_eq(rootPerm.capability, pm.DENY_ACTION);
 
   subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", true);
-  do_check_eq(subPerm.principal.origin, "http://sub.example.com");
+  do_check_eq(subPerm.host, "sub.example.com");
   do_check_eq(subPerm.capability, pm.PROMPT_ACTION);
 
   subPerm = pm.getPermissionObject(subPrincipal, "test/pobject", false);
-  do_check_eq(subPerm.principal.origin, "http://sub.example.com");
+  do_check_eq(subPerm.host, "sub.example.com");
   do_check_eq(subPerm.capability, pm.PROMPT_ACTION);
 
   subPerm = pm.getPermissionObject(subSubPrincipal, "test/pobject", true);
   do_check_null(subPerm);
 
   subPerm = pm.getPermissionObject(subSubPrincipal, "test/pobject", false);
-  do_check_eq(subPerm.principal.origin, "http://sub.example.com");
+  do_check_eq(subPerm.host, "sub.example.com");
   do_check_eq(subPerm.capability, pm.PROMPT_ACTION);
 
   pm.removeFromPrincipal(principal, "test/pobject");
 
   rootPerm = pm.getPermissionObject(principal, "test/pobject", true);
   do_check_null(rootPerm);
 }
--- a/extensions/cookie/test/unit/test_permmanager_load_invalid_entries.js
+++ b/extensions/cookie/test/unit/test_permmanager_load_invalid_entries.js
@@ -116,17 +116,17 @@ function run_test() {
   let earliestNow = Number(Date.now());
   // Initialize the permission manager service
   var pm = Cc["@mozilla.org/permissionmanager;1"]
              .getService(Ci.nsIPermissionManager);
   let latestNow = Number(Date.now());
 
   // The schema should be upgraded to 4, and a 'modificationTime' column should
   // exist with all records having a value of 0.
-  do_check_eq(connection.schemaVersion, 5);
+  do_check_eq(connection.schemaVersion, 4);
 
   let select = connection.createStatement("SELECT modificationTime FROM moz_hosts")
   let numMigrated = 0;
   while (select.executeStep()) {
     let thisModTime = select.getInt64(0);
     do_check_true(thisModTime == 0, "new modifiedTime field is correct");
     numMigrated += 1;
   }
--- a/extensions/cookie/test/unit/test_permmanager_local_files.js
+++ b/extensions/cookie/test/unit/test_permmanager_local_files.js
@@ -34,9 +34,15 @@ function run_test() {
   let fileInDirPrincipal = getPrincipalFromURIString("file:///foo/bar/foobar.txt");
   do_check_eq(pm.testPermissionFromPrincipal(fileInDirPrincipal, "test/local-files"), pm.UNKNOWN_ACTION);
 
   // Revert "file:///foo/bar" permission and check that it has been correctly taken into account.
   pm.removeFromPrincipal(principal, "test/local-files");
   do_check_eq(pm.testPermissionFromPrincipal(principal, "test/local-files"), pm.UNKNOWN_ACTION);
   do_check_eq(pm.testPermissionFromPrincipal(witnessPrincipal, "test/local-files"), pm.UNKNOWN_ACTION);
   do_check_eq(pm.testPermissionFromPrincipal(fileInDirPrincipal, "test/local-files"), pm.UNKNOWN_ACTION);
-}
+
+  // Add the magic "<file>" permission and make sure all "file://" now have the permission.
+  pm.addFromPrincipal(getPrincipalFromURIString("http://<file>"), "test/local-files", pm.ALLOW_ACTION, 0, 0);
+  do_check_eq(pm.testPermissionFromPrincipal(principal, "test/local-files"), pm.ALLOW_ACTION);
+  do_check_eq(pm.testPermissionFromPrincipal(witnessPrincipal, "test/local-files"), pm.ALLOW_ACTION);
+  do_check_eq(pm.testPermissionFromPrincipal(fileInDirPrincipal, "test/local-files"), pm.ALLOW_ACTION);
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/unit/test_permmanager_mailto.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function run_test() {
+  // initialize the permission manager service
+  const kTestAddr = "test@example.org";
+  const kType = "test-mailto";
+  const kCapability = 1;
+
+  // make a mailto: URI with parameters
+  let uri = Services.io.newURI("mailto:" + kTestAddr + "?subject=test", null,
+                               null);
+
+  // add a permission entry for that URI
+  Services.perms.add(uri, kType, kCapability);
+  do_check_true(permission_exists(kTestAddr, kType, kCapability));
+
+  // remove the permission, and make sure it was removed
+  Services.perms.remove(uri, kType);
+  do_check_false(permission_exists(kTestAddr, kType, kCapability));
+
+  uri = Services.io.newURI("mailto:" + kTestAddr, null, null);
+  Services.perms.add(uri, kType, kCapability);
+  do_check_true(permission_exists(kTestAddr, kType, kCapability));
+
+  Services.perms.remove(uri, kType);
+  do_check_false(permission_exists(kTestAddr, kType, kCapability));
+}
+
+function permission_exists(aHost, aType, aCapability) {
+  let e = Services.perms.enumerator;
+  while (e.hasMoreElements()) {
+    let perm = e.getNext().QueryInterface(Ci.nsIPermission);
+    if (perm.host == aHost &&
+        perm.type == aType &&
+        perm.capability == aCapability) {
+      return true;
+    }
+  }
+  return false;
+}
deleted file mode 100644
--- a/extensions/cookie/test/unit/test_permmanager_matches.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function matches_always(perm, principals) {
-  principals.forEach((principal) => {
-    do_check_true(perm.matches(principal, true), "perm: " + perm.principal.origin + ", princ: " + principal.origin);
-    do_check_true(perm.matches(principal, false), "perm: " + perm.principal.origin + ", princ: " + principal.origin);
-  });
-}
-
-function matches_weak(perm, principals) {
-  principals.forEach((principal) => {
-    do_check_false(perm.matches(principal, true), "perm: " + perm.principal.origin + ", princ: " + principal.origin);
-    do_check_true(perm.matches(principal, false), "perm: " + perm.principal.origin + ", princ: " + principal.origin);
-  });
-}
-
-function matches_never(perm, principals) {
-  principals.forEach((principal) => {
-    do_check_false(perm.matches(principal, true), "perm: " + perm.principal.origin + ", princ: " + principal.origin);
-    do_check_false(perm.matches(principal, false), "perm: " + perm.principal.origin + ", princ: " + principal.origin);
-  });
-}
-
-function run_test() {
-  // initialize the permission manager service
-  let pm = Cc["@mozilla.org/permissionmanager;1"].
-        getService(Ci.nsIPermissionManager);
-
-  let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
-        .getService(Ci.nsIScriptSecurityManager);
-
-  // Add some permissions
-  let uri0 = NetUtil.newURI("http://google.com/search?q=foo#hashtag", null, null);
-  let uri1 = NetUtil.newURI("http://hangouts.google.com/subdir", null, null);
-  let uri2 = NetUtil.newURI("http://google.org/", null, null);
-  let uri3 = NetUtil.newURI("https://google.com/some/random/subdirectory", null, null);
-  let uri4 = NetUtil.newURI("https://hangouts.google.com/#!/hangout", null, null);
-  let uri5 = NetUtil.newURI("http://google.com:8096/", null, null);
-
-  let uri0_n_n = secMan.getNoAppCodebasePrincipal(uri0);
-  let uri1_n_n = secMan.getNoAppCodebasePrincipal(uri1);
-  let uri2_n_n = secMan.getNoAppCodebasePrincipal(uri2);
-  let uri3_n_n = secMan.getNoAppCodebasePrincipal(uri3);
-  let uri4_n_n = secMan.getNoAppCodebasePrincipal(uri4);
-  let uri5_n_n = secMan.getNoAppCodebasePrincipal(uri5);
-
-  let uri0_1000_n = secMan.getAppCodebasePrincipal(uri0, 1000, false);
-  let uri1_1000_n = secMan.getAppCodebasePrincipal(uri1, 1000, false);
-  let uri2_1000_n = secMan.getAppCodebasePrincipal(uri2, 1000, false);
-  let uri3_1000_n = secMan.getAppCodebasePrincipal(uri3, 1000, false);
-  let uri4_1000_n = secMan.getAppCodebasePrincipal(uri4, 1000, false);
-  let uri5_1000_n = secMan.getAppCodebasePrincipal(uri5, 1000, false);
-
-  let uri0_1000_y = secMan.getAppCodebasePrincipal(uri0, 1000, true);
-  let uri1_1000_y = secMan.getAppCodebasePrincipal(uri1, 1000, true);
-  let uri2_1000_y = secMan.getAppCodebasePrincipal(uri2, 1000, true);
-  let uri3_1000_y = secMan.getAppCodebasePrincipal(uri3, 1000, true);
-  let uri4_1000_y = secMan.getAppCodebasePrincipal(uri4, 1000, true);
-  let uri5_1000_y = secMan.getAppCodebasePrincipal(uri5, 1000, true);
-
-  let uri0_2000_n = secMan.getAppCodebasePrincipal(uri0, 2000, false);
-  let uri1_2000_n = secMan.getAppCodebasePrincipal(uri1, 2000, false);
-  let uri2_2000_n = secMan.getAppCodebasePrincipal(uri2, 2000, false);
-  let uri3_2000_n = secMan.getAppCodebasePrincipal(uri3, 2000, false);
-  let uri4_2000_n = secMan.getAppCodebasePrincipal(uri4, 2000, false);
-  let uri5_2000_n = secMan.getAppCodebasePrincipal(uri5, 2000, false);
-
-  let uri0_2000_y = secMan.getAppCodebasePrincipal(uri0, 2000, true);
-  let uri1_2000_y = secMan.getAppCodebasePrincipal(uri1, 2000, true);
-  let uri2_2000_y = secMan.getAppCodebasePrincipal(uri2, 2000, true);
-  let uri3_2000_y = secMan.getAppCodebasePrincipal(uri3, 2000, true);
-  let uri4_2000_y = secMan.getAppCodebasePrincipal(uri4, 2000, true);
-  let uri5_2000_y = secMan.getAppCodebasePrincipal(uri5, 2000, true);
-
-  pm.addFromPrincipal(uri0_n_n, "test/matches", pm.ALLOW_ACTION);
-  let perm_n_n = pm.getPermissionObject(uri0_n_n, "test/matches", true);
-  pm.addFromPrincipal(uri0_1000_n, "test/matches", pm.ALLOW_ACTION);
-  let perm_1000_n = pm.getPermissionObject(uri0_1000_n, "test/matches", true);
-  pm.addFromPrincipal(uri0_1000_y, "test/matches", pm.ALLOW_ACTION);
-  let perm_1000_y = pm.getPermissionObject(uri0_1000_y, "test/matches", true);
-  pm.addFromPrincipal(uri0_2000_n, "test/matches", pm.ALLOW_ACTION);
-  let perm_2000_n = pm.getPermissionObject(uri0_2000_n, "test/matches", true);
-  pm.addFromPrincipal(uri0_2000_y, "test/matches", pm.ALLOW_ACTION);
-  let perm_2000_y = pm.getPermissionObject(uri0_2000_y, "test/matches", true);
-
-  matches_always(perm_n_n, [uri0_n_n]);
-  matches_weak(perm_n_n, [uri1_n_n]);
-  matches_never(perm_n_n, [uri2_n_n, uri3_n_n, uri4_n_n, uri5_n_n,
-                           uri0_1000_n, uri1_1000_n, uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
-                           uri0_1000_y, uri1_1000_y, uri2_1000_y, uri3_1000_y, uri4_1000_y, uri5_1000_y,
-                           uri0_2000_n, uri1_2000_n, uri2_2000_n, uri3_2000_n, uri4_2000_n, uri5_2000_n,
-                           uri0_2000_y, uri1_2000_y, uri2_2000_y, uri3_2000_y, uri4_2000_y, uri5_2000_y]);
-
-  matches_always(perm_1000_n, [uri0_1000_n]);
-  matches_weak(perm_1000_n, [uri1_1000_n]);
-  matches_never(perm_1000_n, [uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
-                              uri0_n_n, uri1_n_n, uri2_n_n, uri3_n_n, uri4_n_n, uri5_n_n,
-                              uri0_1000_y, uri1_1000_y, uri2_1000_y, uri3_1000_y, uri4_1000_y, uri5_1000_y,
-                              uri0_2000_n, uri1_2000_n, uri2_2000_n, uri3_2000_n, uri4_2000_n, uri5_2000_n,
-                              uri0_2000_y, uri1_2000_y, uri2_2000_y, uri3_2000_y, uri4_2000_y, uri5_2000_y]);
-
-  matches_always(perm_1000_y, [uri0_1000_y]);
-  matches_weak(perm_1000_y, [uri1_1000_y]);
-  matches_never(perm_1000_y, [uri2_1000_y, uri3_1000_y, uri4_1000_y, uri5_1000_y,
-                              uri0_n_n, uri1_n_n, uri2_n_n, uri3_n_n, uri4_n_n, uri5_n_n,
-                              uri0_1000_n, uri1_1000_n, uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
-                              uri0_2000_n, uri1_2000_n, uri2_2000_n, uri3_2000_n, uri4_2000_n, uri5_2000_n,
-                              uri0_2000_y, uri1_2000_y, uri2_2000_y, uri3_2000_y, uri4_2000_y, uri5_2000_y]);
-
-  matches_always(perm_2000_n, [uri0_2000_n]);
-  matches_weak(perm_2000_n, [uri1_2000_n]);
-  matches_never(perm_2000_n, [uri2_2000_n, uri3_2000_n, uri4_2000_n, uri5_2000_n,
-                              uri0_n_n, uri1_n_n, uri2_n_n, uri3_n_n, uri4_n_n, uri5_n_n,
-                              uri0_2000_y, uri1_2000_y, uri2_2000_y, uri3_2000_y, uri4_2000_y, uri5_2000_y,
-                              uri0_1000_n, uri1_1000_n, uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
-                              uri0_1000_y, uri1_1000_y, uri2_1000_y, uri3_1000_y, uri4_1000_y, uri5_1000_y]);
-
-  matches_always(perm_2000_y, [uri0_2000_y]);
-  matches_weak(perm_2000_y, [uri1_2000_y]);
-  matches_never(perm_2000_y, [uri2_2000_y, uri3_2000_y, uri4_2000_y, uri5_2000_y,
-                              uri0_n_n, uri1_n_n, uri2_n_n, uri3_n_n, uri4_n_n, uri5_n_n,
-                              uri0_2000_n, uri1_2000_n, uri2_2000_n, uri3_2000_n, uri4_2000_n, uri5_2000_n,
-                              uri0_1000_n, uri1_1000_n, uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
-                              uri0_1000_y, uri1_1000_y, uri2_1000_y, uri3_1000_y, uri4_1000_y, uri5_1000_y]);
-
-  // Clean up!
-  pm.removeAll();
-}
deleted file mode 100644
--- a/extensions/cookie/test/unit/test_permmanager_matchesuri.js
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function matches_always(perm, uris) {
-  uris.forEach((uri) => {
-    do_check_true(perm.matchesURI(uri, true), "perm: " + perm.principal.origin + ", URI: " + uri.spec);
-    do_check_true(perm.matchesURI(uri, false), "perm: " + perm.principal.origin + ", URI: " + uri.spec);
-  });
-}
-
-function matches_weak(perm, uris) {
-  uris.forEach((uri) => {
-    do_check_false(perm.matchesURI(uri, true), "perm: " + perm.principal.origin + ", URI: " + uri.spec);
-    do_check_true(perm.matchesURI(uri, false), "perm: " + perm.principal.origin + ", URI: " + uri.spec);
-  });
-}
-
-function matches_never(perm, uris) {
-  uris.forEach((uri) => {
-    do_check_false(perm.matchesURI(uri, true), "perm: " + perm.principal.origin + ", URI: " + uri.spec);
-    do_check_false(perm.matchesURI(uri, false), "perm: " + perm.principal.origin + ", URI: " + uri.spec);
-  });
-}
-
-function mk_permission(uri, isAppPermission = false) {
-  let pm = Cc["@mozilla.org/permissionmanager;1"].
-        getService(Ci.nsIPermissionManager);
-
-  let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
-        .getService(Ci.nsIScriptSecurityManager);
-
-  // Get the permission from the principal!
-  let principal = isAppPermission ?
-        secMan.getAppCodebasePrincipal(uri, 1000, false) :
-        secMan.getNoAppCodebasePrincipal(uri);
-
-  pm.addFromPrincipal(principal, "test/matchesuri", pm.ALLOW_ACTION);
-  let permission = pm.getPermissionObject(principal, "test/matchesuri", true);
-
-  return permission;
-}
-
-function run_test() {
-  // initialize the permission manager service
-  let pm = Cc["@mozilla.org/permissionmanager;1"].
-        getService(Ci.nsIPermissionManager);
-
-  let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
-        .getService(Ci.nsIScriptSecurityManager);
-
-  let fileprefix = "file:///";
-  if (Services.appinfo.OS == "WINNT") {
-    // Windows rejects files if they don't have a drive. See Bug 1180870
-    fileprefix += "c:/";
-  }
-
-  // Add some permissions
-  let uri0 = NetUtil.newURI("http://google.com:9091/just/a/path", null, null);
-  let uri1 = NetUtil.newURI("http://hangouts.google.com:9091/some/path", null, null);
-  let uri2 = NetUtil.newURI("http://google.com:9091/", null, null);
-  let uri3 = NetUtil.newURI("http://google.org:9091/", null, null);
-  let uri4 = NetUtil.newURI("http://deeper.hangouts.google.com:9091/", null, null);
-  let uri5 = NetUtil.newURI("https://google.com/just/a/path", null, null);
-  let uri6 = NetUtil.newURI("https://hangouts.google.com", null, null);
-  let uri7 = NetUtil.newURI("https://google.com/", null, null);
-
-  let fileuri1 = NetUtil.newURI(fileprefix + "a/file/path", null, null);
-  let fileuri2 = NetUtil.newURI(fileprefix + "a/file/path/deeper", null, null);
-  let fileuri3 = NetUtil.newURI(fileprefix + "a/file/otherpath", null, null);
-
-  {
-    let perm = mk_permission(uri0);
-    matches_always(perm, [uri0, uri2]);
-    matches_weak(perm, [uri1, uri4]);
-    matches_never(perm, [uri3, uri5, uri6, uri7, fileuri1, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(uri1);
-    matches_always(perm, [uri1]);
-    matches_weak(perm, [uri4]);
-    matches_never(perm, [uri0, uri2, uri3, uri5, uri6, uri7, fileuri1, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(uri2);
-    matches_always(perm, [uri0, uri2]);
-    matches_weak(perm, [uri1, uri4]);
-    matches_never(perm, [uri3, uri5, uri6, uri7, fileuri1, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(uri3);
-    matches_always(perm, [uri3]);
-    matches_weak(perm, []);
-    matches_never(perm, [uri1, uri2, uri4, uri5, uri6, uri7, fileuri1, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(uri4);
-    matches_always(perm, [uri4]);
-    matches_weak(perm, []);
-    matches_never(perm, [uri1, uri2, uri3, uri5, uri6, uri7, fileuri1, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(uri5);
-    matches_always(perm, [uri5, uri7]);
-    matches_weak(perm, [uri6]);
-    matches_never(perm, [uri0, uri1, uri2, uri3, uri4, fileuri1, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(uri6);
-    matches_always(perm, [uri6]);
-    matches_weak(perm, []);
-    matches_never(perm, [uri0, uri1, uri2, uri3, uri4, uri5, uri7, fileuri1, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(uri7);
-    matches_always(perm, [uri5, uri7]);
-    matches_weak(perm, [uri6]);
-    matches_never(perm, [uri0, uri1, uri2, uri3, uri4, fileuri1, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(fileuri1);
-    matches_always(perm, [fileuri1]);
-    matches_weak(perm, []);
-    matches_never(perm, [uri0, uri1, uri2, uri3, uri4, uri5, uri6, uri7, fileuri2, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(fileuri2);
-    matches_always(perm, [fileuri2]);
-    matches_weak(perm, []);
-    matches_never(perm, [uri0, uri1, uri2, uri3, uri4, uri5, uri6, uri7, fileuri1, fileuri3]);
-  }
-
-  {
-    let perm = mk_permission(fileuri3);
-    matches_always(perm, [fileuri3]);
-    matches_weak(perm, []);
-    matches_never(perm, [uri0, uri1, uri2, uri3, uri4, uri5, uri6, uri7, fileuri1, fileuri2]);
-  }
-
-  // Clean up!
-  pm.removeAll();
-}
deleted file mode 100644
--- a/extensions/cookie/test/unit/test_permmanager_migrate_4-5.js
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
-                                  "resource://testing-common/PlacesTestUtils.jsm");
-
-let PERMISSIONS_FILE_NAME = "permissions.sqlite";
-
-function GetPermissionsFile(profile)
-{
-  let file = profile.clone();
-  file.append(PERMISSIONS_FILE_NAME);
-  return file;
-}
-
-function run_test() {
-  run_next_test();
-}
-
-add_task(function test() {
-  /* Create and set up the permissions database */
-  let profile = do_get_profile();
-
-  let db = Services.storage.openDatabase(GetPermissionsFile(profile));
-  db.schemaVersion = 4;
-
-  db.executeSimpleSQL(
-    "CREATE TABLE moz_hosts (" +
-      " id INTEGER PRIMARY KEY" +
-      ",host TEXT" +
-      ",type TEXT" +
-      ",permission INTEGER" +
-      ",expireType INTEGER" +
-      ",expireTime INTEGER" +
-      ",modificationTime INTEGER" +
-      ",appId INTEGER" +
-      ",isInBrowserElement INTEGER" +
-    ")");
-
-  let stmtInsert = db.createStatement(
-    "INSERT INTO moz_hosts (" +
-      "id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement" +
-    ") VALUES (" +
-      ":id, :host, :type, :permission, :expireType, :expireTime, :modificationTime, :appId, :isInBrowserElement" +
-    ")");
-
-  let id = 0;
-
-  function insertHost(host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) {
-    stmtInsert.bindByName("id", id++);
-    stmtInsert.bindByName("host", host);
-    stmtInsert.bindByName("type", type);
-    stmtInsert.bindByName("permission", permission);
-    stmtInsert.bindByName("expireType", expireType);
-    stmtInsert.bindByName("expireTime", expireTime);
-    stmtInsert.bindByName("modificationTime", modificationTime);
-    stmtInsert.bindByName("appId", appId);
-    stmtInsert.bindByName("isInBrowserElement", isInBrowserElement);
-
-    try {
-      stmtInsert.executeStep();
-      stmtInsert.reset();
-    } catch (e) {
-      stmtInsert.reset();
-      throw e;
-    }
-  }
-
-  // Add some rows to the database
-  insertHost("foo.com", "A", 1, 0, 0, 0, 0, false);
-  insertHost("foo.com", "A", 1, 0, 0, 0, 1000, false);
-  insertHost("foo.com", "A", 1, 0, 0, 0, 2000, true);
-  insertHost("sub.foo.com", "B", 1, 0, 0, 0, 0, false);
-  insertHost("subber.sub.foo.com", "B", 1, 0, 0, 0, 0, false);
-  insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false);
-  insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false);
-  insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true);
-  insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false);
-  insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false);
-  insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false);
-  insertHost("moz-nullprincipal:{12ahjksd-akjs-asd3-8393-asdu2189asdu}", "B", 1, 0, 0, 0, 0, false);
-  insertHost("<file>", "A", 1, 0, 0, 0, 0, false);
-  insertHost("<file>", "B", 1, 0, 0, 0, 0, false);
-
-  // CLose the db connection
-  stmtInsert.finalize();
-  db.close();
-  stmtInsert = null;
-  db = null;
-
-  let expected = [
-    // The http:// entries under foo.com won't be inserted, as there are history entries for foo.com,
-    // and http://foo.com or a subdomain are never visited.
-    // However, permissions for subdomains of foo.com will be present for both http:// and https://,
-    // as they do not apply to any entry in the history
-    // ["http://foo.com", "A", 1, 0, 0],
-    // ["http://foo.com^appId=1000", "A", 1, 0, 0],
-    // ["http://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
-
-    ["http://sub.foo.com", "B", 1, 0, 0],
-    ["http://subber.sub.foo.com", "B", 1, 0, 0],
-
-    ["https://foo.com", "A", 1, 0, 0],
-    ["https://foo.com^appId=1000", "A", 1, 0, 0],
-    ["https://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
-    ["https://sub.foo.com", "B", 1, 0, 0],
-    ["https://subber.sub.foo.com", "B", 1, 0, 0],
-
-    // bar.ca will have both http:// and https:// for all entries, because the foo did the bar a favour
-    ["http://bar.ca", "B", 1, 0, 0],
-    ["https://bar.ca", "B", 1, 0, 0],
-    ["http://bar.ca^appId=1000", "B", 1, 0, 0],
-    ["https://bar.ca^appId=1000", "B", 1, 0, 0],
-    ["http://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
-    ["https://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
-    ["file:///some/path/to/file.html", "A", 1, 0, 0],
-    ["file:///another/file.html", "A", 1, 0, 0],
-
-    // Because we put ftp://some.subdomain.of.foo.com:8000/some/subdirectory in the history, we should
-    // also have these entries
-    ["ftp://foo.com:8000", "A", 1, 0, 0],
-    ["ftp://foo.com:8000^appId=1000", "A", 1, 0, 0],
-    ["ftp://foo.com:8000^appId=2000&inBrowser=1", "A", 1, 0, 0],
-  ];
-
-  let found = expected.map((it) => 0);
-
-  // Add some places to the places database
-  yield PlacesTestUtils.addVisits(Services.io.newURI("https://foo.com/some/other/subdirectory", null, null));
-  yield PlacesTestUtils.addVisits(Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory", null, null));
-
-  // Force initialization of the nsPermissionManager
-  let enumerator = Services.perms.enumerator;
-  while (enumerator.hasMoreElements()) {
-    let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
-    let isExpected = false;
-
-    expected.forEach((it, i) => {
-      if (permission.principal.origin == it[0] &&
-          permission.type == it[1] &&
-          permission.capability == it[2] &&
-          permission.expireType == it[3] &&
-          permission.expireTime == it[4]) {
-        isExpected = true;
-        found[i]++;
-      }
-    });
-
-    do_check_true(isExpected,
-                  "Permission " + (isExpected ? "should" : "shouldn't") +
-                  " be in permission database: " +
-                  permission.principal.origin + ", " +
-                  permission.type + ", " +
-                  permission.capability + ", " +
-                  permission.expireType + ", " +
-                  permission.expireTime);
-  }
-
-  found.forEach((count, i) => {
-    do_check_true(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
-  });
-});
--- a/extensions/cookie/test/unit/xpcshell.ini
+++ b/extensions/cookie/test/unit/xpcshell.ini
@@ -25,15 +25,13 @@ support-files =
 [test_permmanager_notifications.js]
 [test_permmanager_removeall.js]
 [test_permmanager_removesince.js]
 [test_permmanager_load_invalid_entries.js]
 skip-if = debug == true
 [test_permmanager_idn.js]
 [test_permmanager_subdomains.js]
 [test_permmanager_local_files.js]
+[test_permmanager_mailto.js]
 [test_permmanager_cleardata.js]
 [test_schema_2_migration.js]
 [test_schema_3_migration.js]
 [test_permmanager_removepermission.js]
-[test_permmanager_matchesuri.js]
-[test_permmanager_matches.js]
-[test_permmanager_migrate_4-5.js]
--- a/layout/tools/reftest/reftest-preferences.js
+++ b/layout/tools/reftest/reftest-preferences.js
@@ -60,11 +60,8 @@
     branch.setBoolPref("browser.search.isUS", true);
     branch.setCharPref("browser.search.countryCode", "US");
 
     // Make sure SelfSupport doesn't hit the network.
     branch.setCharPref("browser.selfsupport.url", "https://%(server)s/selfsupport-dummy/");
 
     // Disable periodic updates of service workers.
     branch.setBoolPref("dom.serviceWorkers.periodic-updates.enabled", false);
-
-    // Allow XUL and XBL files to be opened from file:// URIs
-    branch.setBoolPref("dom.allow_XUL_XBL_for_file", true);
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -1172,19 +1172,16 @@ function ServeFiles(manifestPrincipal, d
     gServer.registerDirectory(path + "/", directory);
 
     var secMan = CC[NS_SCRIPTSECURITYMANAGER_CONTRACTID]
                      .getService(CI.nsIScriptSecurityManager);
 
     var testbase = gIOService.newURI("http://localhost:" + gHttpServerPort +
                                      path + dirPath, null, null);
 
-    // Give the testbase URI access to XUL and XBL
-    Services.perms.add(testbase, "allowXULXBL", Services.perms.ALLOW_ACTION);
-
     function FileToURI(file)
     {
         // Only serve relative URIs via the HTTP server, not absolute
         // ones like about:blank.
         var testURI = gIOService.newURI(file, null, testbase);
 
         // XXX necessary?  manifestURL guaranteed to be file, others always HTTP
         secMan.checkLoadURIWithPrincipal(manifestPrincipal, testURI,
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -337,17 +337,17 @@ class RemoteReftest(RefTest):
         options.xrePath = remoteXrePath
         options.utilityPath = remoteUtilityPath
         return 0
 
     def stopWebServer(self, options):
         self.server.stop()
 
     def createReftestProfile(self, options, reftestlist):
-        profile = RefTest.createReftestProfile(self, options, reftestlist, server=options.remoteWebServer, port=options.httpPort)
+        profile = RefTest.createReftestProfile(self, options, reftestlist, server=options.remoteWebServer)
         profileDir = profile.profile
 
         prefs = {}
         prefs["app.update.url.android"] = ""
         prefs["browser.firstrun.show.localepicker"] = False
         prefs["font.size.inflation.emPerLine"] = 0
         prefs["font.size.inflation.minTwips"] = 0
         prefs["reftest.remote"] = True
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -182,18 +182,18 @@ class RefTest(object):
         """
           Sets up a profile for reftest.
           'manifest' is the path to the reftest.list file we want to test with.  This is used in
           the remote subclass in remotereftest.py so we can write it to a preference for the
           bootstrap extension.
         """
 
         locations = mozprofile.permissions.ServerLocations()
-        locations.add_host(server, scheme='http', port=0)
-        locations.add_host(server, scheme='https', port=0)
+        locations.add_host(server, port=0)
+        locations.add_host('<file>', port=0)
 
         # Set preferences for communication between our command line arguments
         # and the reftest harness.  Preferences that are required for reftest
         # to work should instead be set in reftest-cmdline.js .
         prefs = {}
         prefs['reftest.timeout'] = options.timeout * 1000
         if options.totalChunks:
             prefs['reftest.totalChunks'] = options.totalChunks
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -172,18 +172,18 @@ pref("layout.spellcheckDefault", 0);
 
 /* new html5 forms */
 pref("dom.experimental_forms", true);
 pref("dom.forms.number", true);
 
 /* extension manager and xpinstall */
 pref("xpinstall.whitelist.directRequest", false);
 pref("xpinstall.whitelist.fileRequest", false);
-pref("xpinstall.whitelist.add", "https://addons.mozilla.org");
-pref("xpinstall.whitelist.add.180", "https://marketplace.firefox.com");
+pref("xpinstall.whitelist.add", "addons.mozilla.org");
+pref("xpinstall.whitelist.add.180", "marketplace.firefox.com");
 
 pref("xpinstall.signatures.required", false);
 
 pref("extensions.enabledScopes", 1);
 pref("extensions.autoupdate.enabled", true);
 pref("extensions.autoupdate.interval", 86400);
 pref("extensions.update.enabled", false);
 pref("extensions.update.interval", 86400);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1746,31 +1746,31 @@ var BrowserApp = {
               // Set a flag to disable mixed content blocking.
               flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT;
             } else {
               // Set mixedContentChannel to null to re-enable mixed content blocking.
               let docShell = browser.webNavigation.QueryInterface(Ci.nsIDocShell);
               docShell.mixedContentChannel = null;
             }
           } else if (data.contentType === "tracking") {
-            // Convert document URI into the format used by
-            // nsChannelClassifier::ShouldEnableTrackingProtection
-            // (any scheme turned into https is correct)
-            let normalizedUrl = Services.io.newURI("https://" + browser.currentURI.hostPort, null, null);
             if (data.allowContent) {
+              // Convert document URI into the format used by
+              // nsChannelClassifier::ShouldEnableTrackingProtection
+              // (any scheme turned into https is correct)
+              let normalizedUrl = Services.io.newURI("https://" + browser.currentURI.hostPort, null, null);
               // Add the current host in the 'trackingprotection' consumer of
               // the permission manager using a normalized URI. This effectively
               // places this host on the tracking protection white list.
               Services.perms.add(normalizedUrl, "trackingprotection", Services.perms.ALLOW_ACTION);
               Telemetry.addData("TRACKING_PROTECTION_EVENTS", 1);
             } else {
               // Remove the current host from the 'trackingprotection' consumer
               // of the permission manager. This effectively removes this host
               // from the tracking protection white list (any list actually).
-              Services.perms.remove(normalizedUrl, "trackingprotection");
+              Services.perms.remove(browser.currentURI, "trackingprotection");
               Telemetry.addData("TRACKING_PROTECTION_EVENTS", 2);
             }
           }
         }
 
         // Try to use the session history to reload so that framesets are
         // handled properly. If the window has no session history, fall back
         // to using the web navigation's reload method.
--- a/netwerk/base/nsIPermission.idl
+++ b/netwerk/base/nsIPermission.idl
@@ -1,32 +1,39 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
  * 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/. */
 
 #include "nsISupports.idl"
 
-interface nsIPrincipal;
-interface nsIURI;
-
-[scriptable, uuid(bb409a51-2371-4fea-9dc9-b7286a458b8c)]
+[scriptable, uuid(cfb08e46-193c-4be7-a467-d7775fb2a31e)]
 /**
  * This interface defines a "permission" object,
  * used to specify allowed/blocked objects from
  * user-specified sites (cookies, images etc).
  */
 
 interface nsIPermission : nsISupports
 {
     /**
-     * The principal for which this permission applies.
+     * The name of the host for which the permission is set
+     */
+    readonly attribute AUTF8String host;
+
+    /**
+     * The id of the app for which the permission is set.
      */
-    readonly attribute nsIPrincipal principal;
+    readonly attribute unsigned long appId;
+
+    /**
+     * Whether the permission has been set to a page inside a browser element.
+     */
+    readonly attribute boolean isInBrowserElement;
 
     /**
      * a case-sensitive ASCII string, indicating the type of permission
      * (e.g., "cookie", "image", etc).
      * This string is specified by the consumer when adding a permission 
      * via nsIPermissionManager.
      * @see nsIPermissionManager
      */
@@ -44,34 +51,9 @@ interface nsIPermission : nsISupports
      */
     readonly attribute uint32_t expireType;
 
     /**
      * The expiration time of the permission (milliseconds since Jan 1 1970
      * 0:00:00).
      */
     readonly attribute int64_t expireTime;
-
-    /**
-     * Test whether a principal would be affected by this permission.
-     *
-     * @param principal  the principal to test
-     * @param exactHost  If true, only the specific host will be matched,
-     *                   @see nsIPermissionManager::testExactPermission.
-     *                   If false, subdomains will also be searched,
-     *                   @see nsIPermissionManager::testPermission.
-     */
-    boolean matches(in nsIPrincipal principal,
-                    in boolean exactHost);
-
-    /**
-     * Test whether a URI would be affected by this permission.
-     * This performs a matches with a NO_APP_ID identifier.
-     *
-     * @param uri        the uri to test
-     * @param exactHost  If true, only the specific host will be matched,
-     *                   @see nsIPermissionManager::testExactPermission.
-     *                   If false, subdomains will also be searched,
-     *                   @see nsIPermissionManager::testPermission.
-     */
-    boolean matchesURI(in nsIURI uri,
-                       in boolean exactHost);
 };
--- a/netwerk/ipc/NeckoMessageUtils.h
+++ b/netwerk/ipc/NeckoMessageUtils.h
@@ -15,58 +15,72 @@
 #include "TimingStruct.h"
 
 namespace IPC {
 
 // nsIPermissionManager utilities
 
 struct Permission
 {
-  nsCString origin, type;
+  nsCString host, type;
   uint32_t capability, expireType;
   int64_t expireTime;
+  uint32_t appId;
+  bool isInBrowserElement;
 
   Permission() { }
-  Permission(const nsCString& aOrigin,
+  Permission(const nsCString& aHost,
+             const uint32_t aAppId,
+             const bool aIsInBrowserElement,
              const nsCString& aType,
              const uint32_t aCapability,
              const uint32_t aExpireType,
-             const int64_t aExpireTime) : origin(aOrigin),
+             const int64_t aExpireTime) : host(aHost),
                                           type(aType),
                                           capability(aCapability),
                                           expireType(aExpireType),
-                                          expireTime(aExpireTime)
+                                          expireTime(aExpireTime),
+                                          appId(aAppId),
+                                          isInBrowserElement(aIsInBrowserElement)
   {}
 };
 
 template<>
 struct ParamTraits<Permission>
 {
   static void Write(Message* aMsg, const Permission& aParam)
   {
-    WriteParam(aMsg, aParam.origin);
+    WriteParam(aMsg, aParam.host);
     WriteParam(aMsg, aParam.type);
     WriteParam(aMsg, aParam.capability);
     WriteParam(aMsg, aParam.expireType);
     WriteParam(aMsg, aParam.expireTime);
+    WriteParam(aMsg, aParam.appId);
+    WriteParam(aMsg, aParam.isInBrowserElement);
   }
 
   static bool Read(const Message* aMsg, void** aIter, Permission* aResult)
   {
-    return ReadParam(aMsg, aIter, &aResult->origin) &&
+    return ReadParam(aMsg, aIter, &aResult->host) &&
            ReadParam(aMsg, aIter, &aResult->type) &&
            ReadParam(aMsg, aIter, &aResult->capability) &&
            ReadParam(aMsg, aIter, &aResult->expireType) &&
-           ReadParam(aMsg, aIter, &aResult->expireTime);
+           ReadParam(aMsg, aIter, &aResult->expireTime) &&
+           ReadParam(aMsg, aIter, &aResult->appId) &&
+           ReadParam(aMsg, aIter, &aResult->isInBrowserElement);
   }
 
   static void Log(const Permission& p, std::wstring* l)
   {
     l->append(L"(");
-    LogParam(p.origin, l);
+    LogParam(p.host, l);
+    l->append(L", ");
+    LogParam(p.appId, l);
+    l->append(L", ");
+    LogParam(p.isInBrowserElement, l);
     l->append(L", ");
     LogParam(p.capability, l);
     l->append(L", ");
     LogParam(p.expireTime, l);
     l->append(L", ");
     LogParam(p.expireType, l);
     l->append(L")");
   }
--- a/netwerk/test/unit/test_permmgr.js
+++ b/netwerk/test/unit/test_permmgr.js
@@ -1,37 +1,37 @@
 // tests nsIPermissionManager
 
 var hosts = [
   // format: [host, type, permission]
-  ["http://mozilla.org", "cookie", 1],
-  ["http://mozilla.org", "image", 2],
-  ["http://mozilla.org", "popup", 3],
-  ["http://mozilla.com", "cookie", 1],
-  ["http://www.mozilla.com", "cookie", 2],
-  ["http://dev.mozilla.com", "cookie", 3]
+  ["mozilla.org", "cookie", 1],
+  ["mozilla.org", "image", 2],
+  ["mozilla.org", "popup", 3],
+  ["mozilla.com", "cookie", 1],
+  ["www.mozilla.com", "cookie", 2],
+  ["dev.mozilla.com", "cookie", 3]
 ];
 
 var results = [
   // format: [host, type, testPermission result, testExactPermission result]
   // test defaults
-  ["http://localhost", "cookie", 0, 0],
-  ["http://spreadfirefox.com", "cookie", 0, 0],
+  ["localhost", "cookie", 0, 0],
+  ["spreadfirefox.com", "cookie", 0, 0],
   // test different types
-  ["http://mozilla.org", "cookie", 1, 1],
-  ["http://mozilla.org", "image", 2, 2],
-  ["http://mozilla.org", "popup", 3, 3],
+  ["mozilla.org", "cookie", 1, 1],
+  ["mozilla.org", "image", 2, 2],
+  ["mozilla.org", "popup", 3, 3],
   // test subdomains
-  ["http://www.mozilla.org", "cookie", 1, 0],
-  ["http://www.dev.mozilla.org", "cookie", 1, 0],
+  ["www.mozilla.org", "cookie", 1, 0],
+  ["www.dev.mozilla.org", "cookie", 1, 0],
   // test different permissions on subdomains
-  ["http://mozilla.com", "cookie", 1, 1],
-  ["http://www.mozilla.com", "cookie", 2, 2],
-  ["http://dev.mozilla.com", "cookie", 3, 3],
-  ["http://www.dev.mozilla.com", "cookie", 3, 0]
+  ["mozilla.com", "cookie", 1, 1],
+  ["www.mozilla.com", "cookie", 2, 2],
+  ["dev.mozilla.com", "cookie", 3, 3],
+  ["www.dev.mozilla.com", "cookie", 3, 0]
 ];
 
 function run_test() {
   var pm = Components.classes["@mozilla.org/permissionmanager;1"]
                      .getService(Components.interfaces.nsIPermissionManager);
 
   var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                             .getService(Components.interfaces.nsIIOService);
@@ -40,26 +40,26 @@ function run_test() {
                          .getService(Components.interfaces.nsIScriptSecurityManager);
 
   // nsIPermissionManager implementation is an extension; don't fail if it's not there
   if (!pm)
     return;
 
   // put a few hosts in
   for (var i = 0; i < hosts.length; ++i) {
-    let uri = ioService.newURI(hosts[i][0], null, null);
-    let principal = secMan.getNoAppCodebasePrincipal(uri);
+    var uri = ioService.newURI("http://" + hosts[i][0], null, null);
+    var principal = secMan.getNoAppCodebasePrincipal(uri);
 
     pm.addFromPrincipal(principal, hosts[i][1], hosts[i][2]);
   }
 
   // test the result
   for (var i = 0; i < results.length; ++i) {
-    let uri = ioService.newURI(results[i][0], null, null);
-    let principal = secMan.getNoAppCodebasePrincipal(uri);
+    var uri = ioService.newURI("http://" + results[i][0], null, null);
+    var principal = secMan.getNoAppCodebasePrincipal(uri);
 
     do_check_eq(pm.testPermissionFromPrincipal(principal, results[i][1]), results[i][2]);
     do_check_eq(pm.testExactPermissionFromPrincipal(principal, results[i][1]), results[i][3]);
   }
 
   // test the enumerator ...
   var j = 0;
   var perms = new Array();
@@ -67,23 +67,26 @@ function run_test() {
   while (enumerator.hasMoreElements()) {
     perms[j] = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
     ++j;
   }
   do_check_eq(perms.length, hosts.length);
 
   // ... remove all the hosts ...
   for (var j = 0; j < perms.length; ++j) {
-    pm.removePermission(perms[j]);
+    var uri = ioService.newURI("http://" + perms[j].host, null, null);
+    var principal = secMan.getNoAppCodebasePrincipal(uri);
+
+    pm.removeFromPrincipal(principal, perms[j].type);
   }
   
   // ... ensure each and every element is equal ...
   for (var i = 0; i < hosts.length; ++i) {
     for (var j = 0; j < perms.length; ++j) {
-      if (perms[j].matchesURI(ioService.newURI(hosts[i][0], null, null), true) &&
+      if (hosts[i][0] == perms[j].host &&
           hosts[i][1] == perms[j].type &&
           hosts[i][2] == perms[j].capability) {
         perms.splice(j, 1);
         break;
       }
     }
   }
   do_check_eq(perms.length, 0);
@@ -94,15 +97,15 @@ function run_test() {
   // test UTF8 normalization behavior: expect ASCII/ACE host encodings
   var utf8 = "b\u00FCcher.dolske.org"; // "b├╝cher.dolske.org"
   var aceref = "xn--bcher-kva.dolske.org";
   var uri = ioService.newURI("http://" + utf8, null, null);
   pm.add(uri, "utf8", 1);
   var enumerator = pm.enumerator;
   do_check_eq(enumerator.hasMoreElements(), true);
   var ace = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
-  do_check_eq(ace.principal.URI.asciiHost, aceref);
+  do_check_eq(ace.host, aceref);
   do_check_eq(enumerator.hasMoreElements(), false);
 
   // test removeAll()
   pm.removeAll();
   do_check_eq(pm.enumerator.hasMoreElements(), false);
 }
--- a/testing/mozbase/mozprofile/mozprofile/permissions.py
+++ b/testing/mozbase/mozprofile/mozprofile/permissions.py
@@ -226,36 +226,28 @@ class Permissions(object):
 
         # Open database and create table
         permDB = sqlite3.connect(os.path.join(self._profileDir, "permissions.sqlite"))
         cursor = permDB.cursor();
 
         # SQL copied from
         # http://mxr.mozilla.org/mozilla-central/source/extensions/cookie/nsPermissionManager.cpp
         cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
-              id INTEGER PRIMARY KEY
-             ,origin TEXT
-             ,type TEXT
-             ,permission INTEGER
-             ,expireType INTEGER
-             ,expireTime INTEGER
-             ,modificationTime INTEGER
-           )""")
+           id INTEGER PRIMARY KEY,
+           host TEXT,
+           type TEXT,
+           permission INTEGER,
+           expireType INTEGER,
+           expireTime INTEGER)""")
 
         rows = cursor.execute("PRAGMA table_info(moz_hosts)")
         count = len(rows.fetchall())
 
-        using_origin = False
-        # if the db contains 7 columns, we're using user_version 5
-        if count == 7:
-            statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0)"
-            cursor.execute("PRAGMA user_version=5;")
-            using_origin = True
         # if the db contains 9 columns, we're using user_version 4
-        elif count == 9:
+        if count == 9:
             statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0, 0)"
             cursor.execute("PRAGMA user_version=4;")
         # if the db contains 8 columns, we're using user_version 3
         elif count == 8:
             statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0)"
             cursor.execute("PRAGMA user_version=3;")
         else:
             statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0)"
@@ -265,36 +257,18 @@ class Permissions(object):
             # set the permissions
             permissions = { 'allowXULXBL': 'noxul' not in location.options }
             for perm, allow in permissions.iteritems():
                 if allow:
                     permission_type = 1
                 else:
                     permission_type = 2
 
-                if using_origin:
-                    # This is a crude approximation of the origin generation logic from
-                    # nsPrincipal and nsStandardURL. It should suffice for the permissions
-                    # which the test runners will want to insert into the system.
-                    origin = location.scheme + "://" + location.host
-                    if (location.scheme != 'http' or location.port != '80') and \
-                       (location.scheme != 'https' or location.port != '443'):
-                        origin += ':' + str(location.port)
-
-                    cursor.execute(statement,
-                                   (origin, perm, permission_type))
-                else:
-                    # The database is still using a legacy system based on hosts
-                    # We can insert the permission as a host
-                    #
-                    # XXX This codepath should not be hit, as tests are run with
-                    # fresh profiles. However, if it was hit, permissions would
-                    # not be added to the database correctly (bug 1183185).
-                    cursor.execute(statement,
-                                   (location.host, perm, permission_type))
+                cursor.execute(statement,
+                               (location.host, perm, permission_type))
 
         # Commit and close
         permDB.commit()
         cursor.close()
 
     def network_prefs(self, proxy=None):
         """
         take known locations and generate preferences to handle permissions and proxy
--- a/testing/mozbase/mozprofile/tests/bug785146.py
+++ b/testing/mozbase/mozprofile/tests/bug785146.py
@@ -39,12 +39,12 @@ http://127.0.0.1:8888           privileg
         stmt = 'PRAGMA user_version;'
 
         con = sqlite3.connect(perms_db_filename)
         cur = con.cursor()
         cur.execute(stmt)
         entries = cur.fetchall()
 
         schema_version = entries[0][0]
-        self.assertEqual(schema_version, 5)
+        self.assertEqual(schema_version, 2)
 
 if __name__ == '__main__':
     unittest.main()
--- a/testing/mozbase/mozprofile/tests/permissions.py
+++ b/testing/mozbase/mozprofile/tests/permissions.py
@@ -35,26 +35,17 @@ http://127.0.0.1:8888           privileg
             self.locations_file.close()
 
     def write_perm_db(self, version=3):
         permDB = sqlite3.connect(os.path.join(self.profile_dir, "permissions.sqlite"))
         cursor = permDB.cursor()
 
         cursor.execute("PRAGMA user_version=%d;" % version)
 
-        if version == 5:
-            cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
-              id INTEGER PRIMARY KEY,
-              origin TEXT,
-              type TEXT,
-              permission INTEGER,
-              expireType INTEGER,
-              expireTime INTEGER,
-              modificationTime INTEGER)""")
-        elif version == 4:
+        if version == 4:
             cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
                id INTEGER PRIMARY KEY,
                host TEXT,
                type TEXT,
                permission INTEGER,
                expireType INTEGER,
                expireTime INTEGER,
                modificationTime INTEGER,
@@ -74,60 +65,60 @@ http://127.0.0.1:8888           privileg
             cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
                id INTEGER PRIMARY KEY,
                host TEXT,
                type TEXT,
                permission INTEGER,
                expireType INTEGER,
                expireTime INTEGER)""")
         else:
-            raise Exception("version must be 2, 3, 4 or 5")
+            raise Exception("version must be 2, 3 or 4")
 
         permDB.commit()
         cursor.close()
 
     def test_create_permissions_db(self):
         perms = Permissions(self.profile_dir, self.locations_file.name)
         perms_db_filename = os.path.join(self.profile_dir, 'permissions.sqlite')
 
-        select_stmt = 'select origin, type, permission from moz_hosts'
+        select_stmt = 'select host, type, permission from moz_hosts'
 
         con = sqlite3.connect(perms_db_filename)
         cur = con.cursor()
         cur.execute(select_stmt)
         entries = cur.fetchall()
 
         self.assertEqual(len(entries), 3)
 
-        self.assertEqual(entries[0][0], 'http://mochi.test:8888')
+        self.assertEqual(entries[0][0], 'mochi.test')
         self.assertEqual(entries[0][1], 'allowXULXBL')
         self.assertEqual(entries[0][2], 1)
 
-        self.assertEqual(entries[1][0], 'http://127.0.0.1')
+        self.assertEqual(entries[1][0], '127.0.0.1')
         self.assertEqual(entries[1][1], 'allowXULXBL')
         self.assertEqual(entries[1][2], 2)
 
-        self.assertEqual(entries[2][0], 'http://127.0.0.1:8888')
+        self.assertEqual(entries[2][0], '127.0.0.1')
         self.assertEqual(entries[2][1], 'allowXULXBL')
         self.assertEqual(entries[2][2], 1)
 
-        perms._locations.add_host('a.b.c', port='8081', scheme='https', options='noxul')
+        perms._locations.add_host('a.b.c', options='noxul')
 
         cur.execute(select_stmt)
         entries = cur.fetchall()
 
         self.assertEqual(len(entries), 4)
-        self.assertEqual(entries[3][0], 'https://a.b.c:8081')
+        self.assertEqual(entries[3][0], 'a.b.c')
         self.assertEqual(entries[3][1], 'allowXULXBL')
         self.assertEqual(entries[3][2], 2)
 
-        # when creating a DB we should default to user_version==5
+        # when creating a DB we should default to user_version==2
         cur.execute('PRAGMA user_version')
         entries = cur.fetchall()
-        self.assertEqual(entries[0][0], 5)
+        self.assertEqual(entries[0][0], 2)
 
         perms.clean_db()
         # table should be removed
         cur.execute("select * from sqlite_master where type='table'")
         entries = cur.fetchall()
         self.assertEqual(len(entries), 0)
 
     def test_nw_prefs(self):
@@ -164,34 +155,24 @@ http://127.0.0.1:8888           privileg
 
         con = sqlite3.connect(perms_db_filename)
         cur = con.cursor()
         cur.execute(select_stmt)
         entries = cur.fetchall()
 
         self.assertEqual(len(entries), 3)
 
-        columns = {
-            1: 6,
-            2: 6,
-            3: 8,
-            4: 9,
-            5: 7,
-        }[version]
-
+        columns = 9 if version == 4 else (8 if version == 3 else 6)
         self.assertEqual(len(entries[0]), columns)
         for x in range(4, columns):
             self.assertEqual(entries[0][x], 0)
 
     def test_existing_permissions_db_v2(self):
         self.verify_user_version(2)
 
     def test_existing_permissions_db_v3(self):
         self.verify_user_version(3)
 
     def test_existing_permissions_db_v4(self):
         self.verify_user_version(4)
 
-    def test_existing_permissions_db_v5(self):
-        self.verify_user_version(5)
-
 if __name__ == '__main__':
     unittest.main()
--- a/testing/specialpowers/components/SpecialPowersObserver.js
+++ b/testing/specialpowers/components/SpecialPowersObserver.js
@@ -212,26 +212,17 @@ SpecialPowersObserver.prototype = new Sp
         Services.obs.addObserver(this, topic, false);
       }
     },
     observe: function (aSubject, aTopic, aData) {
       var msg = { aData: aData };
       switch (aTopic) {
         case "perm-changed":
           var permission = aSubject.QueryInterface(Ci.nsIPermission);
-
-          // specialPowersAPI will consume this value, and it is used as a
-          // fake permission, but only type and principal.appId will be used.
-          //
-          // We need to ensure that it looks the same as a real permission,
-          // so we fake these properties.
-          msg.permission = {
-            principal: { appId: permission.principal.appId },
-            type: permission.type
-          };
+          msg.permission = { appId: permission.appId, type: permission.type };
         default:
           this._self._sendAsyncMessage("specialpowers-" + aTopic, msg);
       }
     }
   };
 
   /**
    * messageManager callback function
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -962,17 +962,17 @@ SpecialPowersAPI.prototype = {
         }
       } else {
         var found = false;
         for (var i = 0; !found && i < this._self._permissionsUndoStack.length; i++) {
           var undos = this._self._permissionsUndoStack[i];
           for (var j = 0; j < undos.length; j++) {
             var undo = undos[j];
             if (undo.op == this._obsDataMap[aData] &&
-                undo.appId == permission.principal.appId &&
+                undo.appId == permission.appId &&
                 undo.type == permission.type) {
               // Remove this undo item if it has been done by others(not
               // specialpowers itself.)
               undos.splice(j,1);
               found = true;
               break;
             }
           }
--- a/toolkit/forgetaboutsite/ForgetAboutSite.jsm
+++ b/toolkit/forgetaboutsite/ForgetAboutSite.jsm
@@ -135,23 +135,18 @@ this.ForgetAboutSite = {
 
     // Permissions
     let pm = Cc["@mozilla.org/permissionmanager;1"].
              getService(Ci.nsIPermissionManager);
     // Enumerate all of the permissions, and if one matches, remove it
     enumerator = pm.enumerator;
     while (enumerator.hasMoreElements()) {
       let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
-      try {
-        if (hasRootDomain(perm.principal.URI.host, aDomain)) {
-          pm.removePermission(perm);
-        }
-      } catch (e) {
-        /* Ignore entry */
-      }
+      if (hasRootDomain(perm.host, aDomain))
+        pm.removePermission(perm);
     }
 
     // Offline Storages
     let qm = Cc["@mozilla.org/dom/quota/manager;1"].
              getService(Ci.nsIQuotaManager);
     // delete data from both HTTP and HTTPS sites
     let caUtils = {};
     let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
--- a/toolkit/modules/BrowserUtils.jsm
+++ b/toolkit/modules/BrowserUtils.jsm
@@ -100,17 +100,17 @@ this.BrowserUtils = {
     if (aOriginString.startsWith('[')) {
       throw new Error("principalFromOrigin does not support System and Expanded principals");
     }
 
     if (aOriginString.startsWith("moz-nullprincipal:")) {
       throw new Error("principalFromOrigin does not support nsNullPrincipal");
     }
 
-    var parts = aOriginString.split('^');
+    var parts = aOriginString.split('!');
     if (parts.length > 2) {
       throw new Error("bad origin string: " + aOriginString);
     }
 
     var uri = Services.io.newURI(parts[0], null, null);
     var attrs = {};
     // Parse the parameters string into a dictionary.
     (parts[1] || "").split("&").map((x) => x.split('=')).forEach((x) => attrs[x[0]] = x[1]);
--- a/toolkit/modules/PermissionsUtils.jsm
+++ b/toolkit/modules/PermissionsUtils.jsm
@@ -2,59 +2,47 @@
 // 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/.
 
 this.EXPORTED_SYMBOLS = ["PermissionsUtils"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/BrowserUtils.jsm")
 
 
 let gImportedPrefBranches = new Set();
 
 function importPrefBranch(aPrefBranch, aPermission, aAction) {
   let list = Services.prefs.getChildList(aPrefBranch, {});
 
   for (let pref of list) {
-    let origins = "";
+    let hosts = "";
     try {
-      origins = Services.prefs.getCharPref(pref);
+      hosts = Services.prefs.getCharPref(pref);
     } catch (e) {}
 
-    if (!origins)
+    if (!hosts)
       continue;
 
-    origins = origins.split(",");
+    hosts = hosts.split(",");
 
-    for (let origin of origins) {
-      let principals = [];
+    for (let host of hosts) {
+      let uri = null;
       try {
-        principals = [ BrowserUtils.principalFromOrigin(origin) ];
+        uri = Services.io.newURI("http://" + host, null, null);
       } catch (e) {
-        // This preference used to contain a list of hosts. For back-compat
-        // reasons, we convert these hosts into http:// and https:// permissions
-        // on default ports.
         try {
-          let httpURI = Services.io.newURI("http://" + origin, null, null);
-          let httpsURI = Services.io.newURI("https://" + origin, null, null);
-
-          principals = [
-            Services.scriptSecurityManager.getNoAppCodebasePrincipal(httpURI),
-            Services.scriptSecurityManager.getNoAppCodebasePrincipal(httpsURI)
-          ];
+          uri = Services.io.newURI(host, null, null);
         } catch (e2) {}
       }
 
-      for (let principal of principals) {
-        try {
-          Services.perms.addFromPrincipal(principal, aPermission, aAction);
-        } catch (e) {}
-      }
+      try {
+        Services.perms.add(uri, aPermission, aAction);
+      } catch (e) {}
     }
 
     Services.prefs.setCharPref(pref, "");
   }
 }
 
 
 this.PermissionsUtils = {
--- a/toolkit/modules/tests/xpcshell/test_PermissionsUtils.js
+++ b/toolkit/modules/tests/xpcshell/test_PermissionsUtils.js
@@ -18,46 +18,32 @@ function run_test() {
   test_importfromPrefs();
 }
 
 
 function test_importfromPrefs() {
   // Create own preferences to test
   Services.prefs.setCharPref(PREF_ROOT + "whitelist.add.EMPTY", "");
   Services.prefs.setCharPref(PREF_ROOT + "whitelist.add.EMPTY2", ",");
-  Services.prefs.setCharPref(PREF_ROOT + "whitelist.add.TEST", "http://whitelist.example.com");
-  Services.prefs.setCharPref(PREF_ROOT + "whitelist.add.TEST2", "https://whitelist2-1.example.com,http://whitelist2-2.example.com:8080,about:home");
-  Services.prefs.setCharPref(PREF_ROOT + "whitelist.add.TEST3", "whitelist3-1.example.com,about:config"); // legacy style - host only
+  Services.prefs.setCharPref(PREF_ROOT + "whitelist.add.TEST", "whitelist.example.com");
+  Services.prefs.setCharPref(PREF_ROOT + "whitelist.add.TEST2", "whitelist2-1.example.com,whitelist2-2.example.com,about:home");
   Services.prefs.setCharPref(PREF_ROOT + "blacklist.add.EMPTY", "");
-  Services.prefs.setCharPref(PREF_ROOT + "blacklist.add.TEST", "http://blacklist.example.com,");
-  Services.prefs.setCharPref(PREF_ROOT + "blacklist.add.TEST2", ",https://blacklist2-1.example.com,http://blacklist2-2.example.com:8080,about:mozilla");
-  Services.prefs.setCharPref(PREF_ROOT + "blacklist.add.TEST3", "blacklist3-1.example.com,about:preferences"); // legacy style - host only
+  Services.prefs.setCharPref(PREF_ROOT + "blacklist.add.TEST", "blacklist.example.com,");
+  Services.prefs.setCharPref(PREF_ROOT + "blacklist.add.TEST2", ",blacklist2-1.example.com,blacklist2-2.example.com,about:mozilla");
 
   // Check they are unknown in the permission manager prior to importing.
   let whitelisted = ["http://whitelist.example.com",
-                     "https://whitelist2-1.example.com",
-                     "http://whitelist2-2.example.com:8080",
-                     "http://whitelist3-1.example.com",
-                     "https://whitelist3-1.example.com",
-                     "about:config",
+                     "http://whitelist2-1.example.com",
+                     "http://whitelist2-2.example.com",
                      "about:home"];
   let blacklisted = ["http://blacklist.example.com",
-                     "https://blacklist2-1.example.com",
-                     "http://blacklist2-2.example.com:8080",
-                     "http://blacklist3-1.example.com",
-                     "https://blacklist3-1.example.com",
-                     "about:preferences",
+                     "http://blacklist2-1.example.com",
+                     "http://blacklist2-2.example.com",
                      "about:mozilla"];
-  let untouched = ["https://whitelist.example.com",
-                   "https://blacklist.example.com",
-                   "http://whitelist2-1.example.com",
-                   "http://blacklist2-1.example.com",
-                   "https://whitelist2-2.example.com:8080",
-                   "https://blacklist2-2.example.com:8080"];
-  let unknown = whitelisted.concat(blacklisted).concat(untouched);
+  let unknown = whitelisted.concat(blacklisted);
   for (let url of unknown) {
     let uri = Services.io.newURI(url, null, null);
     do_check_eq(Services.perms.testPermission(uri, TEST_PERM), Services.perms.UNKNOWN_ACTION);
   }
 
   // Import them
   PermissionsUtils.importFromPrefs(PREF_ROOT, TEST_PERM);
 
@@ -73,13 +59,9 @@ function test_importfromPrefs() {
   for (let url of whitelisted) {
     let uri = Services.io.newURI(url, null, null);
     do_check_eq(Services.perms.testPermission(uri, TEST_PERM), Services.perms.ALLOW_ACTION);
   }
   for (let url of blacklisted) {
     let uri = Services.io.newURI(url, null, null);
     do_check_eq(Services.perms.testPermission(uri, TEST_PERM), Services.perms.DENY_ACTION);
   }
-  for (let url of untouched) {
-    let uri = Services.io.newURI(url, null, null);
-    do_check_eq(Services.perms.testPermission(uri, TEST_PERM), Services.perms.UNKNOWN_ACTION);
-  }
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
@@ -7,19 +7,19 @@ Components.utils.import("resource://gre/
 // Checks that permissions set in preferences are correctly imported but can
 // be removed by the user.
 
 const XPI_MIMETYPE = "application/x-xpinstall";
 
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
 
-  Services.prefs.setCharPref("xpinstall.whitelist.add", "https://test1.com,https://test2.com");
-  Services.prefs.setCharPref("xpinstall.whitelist.add.36", "https://test3.com,https://www.test4.com");
-  Services.prefs.setCharPref("xpinstall.whitelist.add.test5", "https://test5.com");
+  Services.prefs.setCharPref("xpinstall.whitelist.add", "test1.com,test2.com");
+  Services.prefs.setCharPref("xpinstall.whitelist.add.36", "test3.com,www.test4.com");
+  Services.prefs.setCharPref("xpinstall.whitelist.add.test5", "test5.com");
 
   Services.perms.add(NetUtil.newURI("https://www.test9.com"), "install",
                      AM_Ci.nsIPermissionManager.ALLOW_ACTION);
 
   startupManager();
 
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("http://test1.com")));
--- a/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js
@@ -25,19 +25,19 @@ function clear_imported_preferences_cach
   scope.gImportedPrefBranches.clear();
 }
 
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
 
   // Create own preferences to test
   Services.prefs.setCharPref("xpinstall.whitelist.add.EMPTY", "");
-  Services.prefs.setCharPref("xpinstall.whitelist.add.TEST", "http://whitelist.example.com");
+  Services.prefs.setCharPref("xpinstall.whitelist.add.TEST", "whitelist.example.com");
   Services.prefs.setCharPref("xpinstall.blacklist.add.EMPTY", "");
-  Services.prefs.setCharPref("xpinstall.blacklist.add.TEST", "http://blacklist.example.com");
+  Services.prefs.setCharPref("xpinstall.blacklist.add.TEST", "blacklist.example.com");
 
   // Get list of preferences to check
   var whitelistPreferences = Services.prefs.getChildList(PREF_XPI_WHITELIST_PERMISSIONS, {});
   var blacklistPreferences = Services.prefs.getChildList(PREF_XPI_BLACKLIST_PERMISSIONS, {});
   var preferences = whitelistPreferences.concat(blacklistPreferences);
 
   startupManager();
 
@@ -48,24 +48,24 @@ function run_test() {
   do_check_permission_prefs(preferences);
 
 
   // Import can also be triggerred by an observer notification by any other area
   // of code, such as a permissions management UI.
 
   // First, request to flush all permissions
   clear_imported_preferences_cache();
-  Services.prefs.setCharPref("xpinstall.whitelist.add.TEST2", "https://whitelist2.example.com");
+  Services.prefs.setCharPref("xpinstall.whitelist.add.TEST2", "whitelist2.example.com");
   Services.obs.notifyObservers(null, "flush-pending-permissions", "install");
   do_check_permission_prefs(preferences);
 
   // Then, request to flush just install permissions
   clear_imported_preferences_cache();
-  Services.prefs.setCharPref("xpinstall.whitelist.add.TEST3", "https://whitelist3.example.com");
+  Services.prefs.setCharPref("xpinstall.whitelist.add.TEST3", "whitelist3.example.com");
   Services.obs.notifyObservers(null, "flush-pending-permissions", "");
   do_check_permission_prefs(preferences);
 
   // And a request to flush some other permissions sholdn't flush install permissions
   clear_imported_preferences_cache();
-  Services.prefs.setCharPref("xpinstall.whitelist.add.TEST4", "https://whitelist4.example.com");
+  Services.prefs.setCharPref("xpinstall.whitelist.add.TEST4", "whitelist4.example.com");
   Services.obs.notifyObservers(null, "flush-pending-permissions", "lolcats");
-  do_check_eq(Services.prefs.getCharPref("xpinstall.whitelist.add.TEST4"), "https://whitelist4.example.com");
+  do_check_eq(Services.prefs.getCharPref("xpinstall.whitelist.add.TEST4"), "whitelist4.example.com");
 }