diff --git a/browser/app/permissions b/browser/app/permissions index cc37101dd37..bc3cddbbf43 100644 --- 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 diff --git a/browser/base/content/browser-plugins.js b/browser/base/content/browser-plugins.js index e17cf0f098e..dfad5d8965c 100644 --- a/browser/base/content/browser-plugins.js +++ b/browser/base/content/browser-plugins.js @@ -44,14 +44,14 @@ var gPluginHandler = { 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); @@ -216,8 +216,8 @@ var gPluginHandler = { }); }, - 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 @@ -295,6 +295,7 @@ var gPluginHandler = { primaryPlugin: primaryPluginPermission, pluginData: pluginData, principal: principal, + host: host, }; PopupNotifications.show(browser, "click-to-play-plugins", "", "plugins-notification-icon", @@ -315,10 +316,8 @@ var gPluginHandler = { 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 @@ -381,22 +380,22 @@ var gPluginHandler = { 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 = [ diff --git a/browser/base/content/browser-trackingprotection.js b/browser/base/content/browser-trackingprotection.js index e32bd1c08df..7c7ed7db5e5 100644 --- a/browser/base/content/browser-trackingprotection.js +++ b/browser/base/content/browser-trackingprotection.js @@ -99,11 +99,7 @@ let TrackingProtection = { // 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. diff --git a/browser/base/content/pageinfo/pageInfo.js b/browser/base/content/pageinfo/pageInfo.js index d216346c293..c7b67c423c0 100644 --- a/browser/base/content/pageinfo/pageInfo.js +++ b/browser/base/content/pageinfo/pageInfo.js @@ -1117,9 +1117,8 @@ var imagePermissionObserver = { 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); - } } } } diff --git a/browser/base/content/pageinfo/permissions.js b/browser/base/content/pageinfo/permissions.js index eaf5824151d..a67ecd07b66 100644 --- a/browser/base/content/pageinfo/permissions.js +++ b/browser/base/content/pageinfo/permissions.js @@ -18,7 +18,7 @@ var permissionObserver = { { 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")) @@ -35,7 +35,7 @@ function onLoadPermission() 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); diff --git a/browser/base/content/test/general/browser_bug592338.js b/browser/base/content/test/general/browser_bug592338.js index 015459b0dc5..99544d87a8b 100644 --- a/browser/base/content/test/general/browser_bug592338.js +++ b/browser/base/content/test/general/browser_bug592338.js @@ -48,7 +48,7 @@ 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() { diff --git a/browser/base/content/test/plugins/head.js b/browser/base/content/test/plugins/head.js index c1290ed19eb..4c5d8dd382a 100644 --- a/browser/base/content/test/plugins/head.js +++ b/browser/base/content/test/plugins/head.js @@ -238,7 +238,7 @@ function clearAllPluginPermissions() { 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); } } diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index d212b31d04c..be7463f4f09 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -2432,9 +2432,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. 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(); @@ -2442,13 +2442,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -2564,8 +2561,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. 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"); @@ -2604,7 +2601,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. - + diff --git a/browser/components/preferences/aboutPermissions.js b/browser/components/preferences/aboutPermissions.js index 9b0bcce885a..50175e4493d 100644 --- a/browser/components/preferences/aboutPermissions.js +++ b/browser/components/preferences/aboutPermissions.js @@ -17,9 +17,6 @@ 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); @@ -29,7 +26,7 @@ let gPlacesDatabase = Cc["@mozilla.org/browser/nav-history-service;1"]. 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 " + @@ -49,11 +46,14 @@ let gVisitStmt = gPlacesDatabase.createAsyncStatement( 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 = { @@ -75,10 +75,16 @@ Site.prototype = { } } - // 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)); }, @@ -90,9 +96,7 @@ Site.prototype = { * 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) { @@ -135,9 +139,9 @@ Site.prototype = { 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; @@ -162,7 +166,9 @@ Site.prototype = { 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); }, /** @@ -173,7 +179,7 @@ Site.prototype = { * e.g. "cookie", "geo", "indexedDB", "popup", "image" */ clearPermission: function Site_clearPermission(aType) { - Services.perms.removeFromPrincipal(this.principal, aType); + Services.perms.remove(this.httpURI, aType); }, /** @@ -183,14 +189,13 @@ Site.prototype = { * @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); } } @@ -212,27 +217,27 @@ Site.prototype = { * @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); } } @@ -361,7 +366,7 @@ let AboutPermissions = { 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: {}, @@ -467,9 +472,9 @@ let AboutPermissions = { 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); } @@ -507,11 +512,8 @@ let AboutPermissions = { 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(); }, @@ -560,8 +562,7 @@ let AboutPermissions = { 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 } @@ -576,8 +577,7 @@ let AboutPermissions = { 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 } @@ -592,7 +592,7 @@ let AboutPermissions = { 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++; } @@ -603,15 +603,15 @@ let AboutPermissions = { /** * 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); }, @@ -624,7 +624,7 @@ let AboutPermissions = { 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); @@ -633,7 +633,7 @@ let AboutPermissions = { // 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); }, @@ -686,16 +686,16 @@ let AboutPermissions = { * 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]; } } }, @@ -711,9 +711,9 @@ let AboutPermissions = { 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"); @@ -768,9 +768,9 @@ let AboutPermissions = { // 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; @@ -825,18 +825,18 @@ let AboutPermissions = { * 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}); } }, @@ -877,11 +877,9 @@ let AboutPermissions = { * 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"); diff --git a/browser/components/preferences/advanced.js b/browser/components/preferences/advanced.js index a1210971da3..f2fd2cb23b2 100644 --- a/browser/components/preferences/advanced.js +++ b/browser/components/preferences/advanced.js @@ -9,7 +9,6 @@ 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, @@ -472,7 +471,7 @@ var gAdvancedPane = { 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; } @@ -509,7 +508,7 @@ var gAdvancedPane = { 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", @@ -535,8 +534,7 @@ var gAdvancedPane = { { 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); @@ -545,18 +543,13 @@ var gAdvancedPane = { 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); @@ -564,14 +557,25 @@ var gAdvancedPane = { 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(); diff --git a/browser/components/preferences/in-content/advanced.js b/browser/components/preferences/in-content/advanced.js index 629b167762f..a8f65a9b7f3 100644 --- a/browser/components/preferences/in-content/advanced.js +++ b/browser/components/preferences/in-content/advanced.js @@ -502,7 +502,7 @@ var gAdvancedPane = { 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; } @@ -544,7 +544,7 @@ var gAdvancedPane = { 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", @@ -570,8 +570,7 @@ var gAdvancedPane = { { 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); @@ -580,18 +579,13 @@ var gAdvancedPane = { 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"]. @@ -600,15 +594,26 @@ var gAdvancedPane = { 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(); diff --git a/browser/components/preferences/permissions.js b/browser/components/preferences/permissions.js index 8a531573f63..ec55dfb432d 100644 --- a/browser/components/preferences/permissions.js +++ b/browser/components/preferences/permissions.js @@ -9,10 +9,10 @@ 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; } @@ -35,7 +35,7 @@ var gPermissionManager = { 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 ""; @@ -82,17 +82,10 @@ var gPermissionManager = { 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"); @@ -103,11 +96,11 @@ var gPermissionManager = { 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; @@ -116,14 +109,14 @@ var gPermissionManager = { } } - 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 = ""; @@ -138,15 +131,15 @@ var gPermissionManager = { _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); } }, @@ -283,7 +276,7 @@ var gPermissionManager = { } 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; } @@ -370,11 +363,13 @@ var gPermissionManager = { 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(); @@ -397,7 +392,7 @@ var gPermissionManager = { // 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; @@ -409,19 +404,20 @@ var gPermissionManager = { (!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); @@ -431,15 +427,15 @@ var gPermissionManager = { } }, - 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) diff --git a/browser/components/preferences/tests/browser_chunk_permissions.js b/browser/components/preferences/tests/browser_chunk_permissions.js index 4c53c6c7fe2..cf88dd32911 100644 --- a/browser/components/preferences/tests/browser_chunk_permissions.js +++ b/browser/components/preferences/tests/browser_chunk_permissions.js @@ -103,11 +103,11 @@ var tests = [ 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(); @@ -119,11 +119,11 @@ var tests = [ 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(); @@ -131,7 +131,7 @@ var tests = [ } ]; -function getSiteItem(aPrePath) { +function getSiteItem(aHost) { return gBrowser.contentDocument. - querySelector(".site[value='" + aPrePath + "']"); + querySelector(".site[value='" + aHost + "']"); } diff --git a/browser/components/preferences/tests/browser_cookies_exceptions.js b/browser/components/preferences/tests/browser_cookies_exceptions.js index 92ed070b75c..52798c43b01 100644 --- a/browser/components/preferences/tests/browser_cookies_exceptions.js +++ b/browser/components/preferences/tests/browser_cookies_exceptions.js @@ -20,7 +20,7 @@ var testRunner = { "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 }], }, { @@ -31,7 +31,7 @@ var testRunner = { "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 }], }, { @@ -42,7 +42,7 @@ var testRunner = { "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 }], }, { @@ -52,7 +52,7 @@ var testRunner = { 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) { @@ -61,7 +61,7 @@ var testRunner = { 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); @@ -160,17 +160,12 @@ var testRunner = { 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) { diff --git a/browser/components/preferences/tests/browser_permissions.js b/browser/components/preferences/tests/browser_permissions.js index 84d91e03024..2a896b3e0da 100644 --- a/browser/components/preferences/tests/browser_permissions.js +++ b/browser/components/preferences/tests/browser_permissions.js @@ -115,8 +115,8 @@ var tests = [ 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(); }, @@ -128,9 +128,9 @@ var tests = [ 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 @@ -202,13 +202,13 @@ var tests = [ 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"); @@ -283,7 +283,7 @@ var tests = [ "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 diff --git a/browser/components/preferences/translation.js b/browser/components/preferences/translation.js index 4f353c53e2e..a1ae8988b1b 100644 --- a/browser/components/preferences/translation.js +++ b/browser/components/preferences/translation.js @@ -9,7 +9,6 @@ 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")); @@ -84,7 +83,7 @@ let gTranslationExceptions = { 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); @@ -127,14 +126,14 @@ let gTranslationExceptions = { 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); @@ -189,9 +188,9 @@ let gTranslationExceptions = { 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); } }, @@ -202,9 +201,9 @@ let gTranslationExceptions = { 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(); diff --git a/browser/components/translation/test/browser_translation_exceptions.js b/browser/components/translation/test/browser_translation_exceptions.js index 086614bfd29..25a4b113dff 100644 --- a/browser/components/translation/test/browser_translation_exceptions.js +++ b/browser/components/translation/test/browser_translation_exceptions.js @@ -51,7 +51,7 @@ function getDomainExceptions() { if (perm.type == "translate" && perm.capability == Services.perms.DENY_ACTION) - results.push(perm.principal); + results.push(perm.host); } return results; @@ -181,7 +181,7 @@ let gTests = [ // 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"); diff --git a/browser/components/uitour/test/head.js b/browser/components/uitour/test/head.js index 330a174c622..73e5e4c66b2 100644 --- a/browser/components/uitour/test/head.js +++ b/browser/components/uitour/test/head.js @@ -198,10 +198,8 @@ function loadUITourTestPage(callback, host = "https://example.com/") { 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(); @@ -212,8 +210,7 @@ function UITourTest() { 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() { diff --git a/browser/modules/PluginContent.jsm b/browser/modules/PluginContent.jsm index a188013a11f..5d968dab5dd 100644 --- a/browser/modules/PluginContent.jsm +++ b/browser/modules/PluginContent.jsm @@ -695,6 +695,20 @@ PluginContent.prototype = { 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. */ @@ -762,6 +776,7 @@ PluginContent.prototype = { 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) { @@ -777,11 +792,11 @@ PluginContent.prototype = { 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; } @@ -791,6 +806,7 @@ PluginContent.prototype = { this.global.sendAsyncMessage("PluginContent:ShowClickToPlayNotification", { plugins: [... this.pluginData.values()], showNow: showNow, + host: principalHost, location: location, }, null, principal); }, @@ -873,6 +889,7 @@ PluginContent.prototype = { this.global.sendAsyncMessage("PluginContent:UpdateHiddenPluginUI", { haveInsecure: haveInsecure, actions: [... actions.values()], + host: this._getHostFromPrincipal(principal), location: location, }, null, principal); }, diff --git a/caps/BasePrincipal.cpp b/caps/BasePrincipal.cpp index 2b21258ec9f..3cf84fa2691 100644 --- a/caps/BasePrincipal.cpp +++ b/caps/BasePrincipal.cpp @@ -51,7 +51,7 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const params->Serialize(value); if (!value.IsEmpty()) { - aStr.AppendLiteral("^"); + aStr.AppendLiteral("!"); aStr.Append(NS_ConvertUTF16toUTF8(value)); } } @@ -117,7 +117,7 @@ OriginAttributes::PopulateFromSuffix(const nsACString& aStr) return true; } - if (aStr[0] != '^') { + if (aStr[0] != '!') { return false; } @@ -134,7 +134,7 @@ OriginAttributes::PopulateFromOrigin(const nsACString& aOrigin, { // RFindChar is only available on nsCString. nsCString origin(aOrigin); - int32_t pos = origin.RFindChar('^'); + int32_t pos = origin.RFindChar('!'); if (pos == kNotFound) { aOriginNoSuffix = origin; diff --git a/caps/nsPrincipal.cpp b/caps/nsPrincipal.cpp index 302e6188cfa..ed3b6b017a0 100644 --- a/caps/nsPrincipal.cpp +++ b/caps/nsPrincipal.cpp @@ -14,7 +14,6 @@ #include "pratom.h" #include "nsIURI.h" #include "nsIURL.h" -#include "nsIStandardURL.h" #include "nsIURIWithPrincipal.h" #include "nsJSPrincipals.h" #include "nsIEffectiveTLDService.h" @@ -128,31 +127,6 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin) } } - // 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); @@ -170,14 +144,6 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin) 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 standardURL = do_QueryInterface(origin); - NS_ENSURE_TRUE(standardURL, NS_ERROR_FAILURE); rv = origin->GetAsciiSpec(aOrigin); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/caps/tests/unit/test_origin.js b/caps/tests/unit/test_origin.js index 020ae3a2404..ef462719e7c 100644 --- a/caps/tests/unit/test_origin.js +++ b/caps/tests/unit/test_origin.js @@ -68,33 +68,33 @@ function run_test() { // 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); diff --git a/dom/apps/tests/unit/test_moziapplication.js b/dom/apps/tests/unit/test_moziapplication.js index b7989f82e04..b5609d8564c 100644 --- a/dom/apps/tests/unit/test_moziapplication.js +++ b/dom/apps/tests/unit/test_moziapplication.js @@ -51,7 +51,7 @@ add_test(() => { }); 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"); diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index ea4e78821f3..b4acda4172d 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -53,7 +53,6 @@ #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) @@ -2113,15 +2112,18 @@ ContentChild::RecvAddPermission(const IPC::Permission& permission) MOZ_ASSERT(permissionManager, "We have no permissionManager in the Content process !"); - nsAutoCString originNoSuffix; - OriginAttributes attrs; - attrs.PopulateFromOrigin(permission.origin, originNoSuffix); - nsCOMPtr uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); - NS_ENSURE_SUCCESS(rv, true); + NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host)); + NS_ENSURE_TRUE(uri, true); - nsCOMPtr principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs); + nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); + MOZ_ASSERT(secMan); + + nsCOMPtr principal; + nsresult rv = secMan->GetAppCodebasePrincipal(uri, permission.appId, + permission.isInBrowserElement, + getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, true); // child processes don't care about modification time. int64_t modificationTime = 0; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index a2d750d344e..c2b484bd322 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -2559,12 +2559,12 @@ ContentParent::RecvReadPermissions(InfallibleTArray* aPermissio enumerator->GetNext(getter_AddRefs(supp)); nsCOMPtr perm = do_QueryInterface(supp); - nsCOMPtr 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; @@ -2574,7 +2574,8 @@ ContentParent::RecvReadPermissions(InfallibleTArray* aPermissio int64_t expireTime; perm->GetExpireTime(&expireTime); - aPermissions->AppendElement(IPC::Permission(origin, type, + aPermissions->AppendElement(IPC::Permission(host, appId, + isInBrowserElement, type, capability, expireType, expireTime)); } diff --git a/dom/storage/DOMStorageObserver.cpp b/dom/storage/DOMStorageObserver.cpp index 54ca8401639..29a20ed9872 100644 --- a/dom/storage/DOMStorageObserver.cpp +++ b/dom/storage/DOMStorageObserver.cpp @@ -196,20 +196,8 @@ DOMStorageObserver::Observe(nsISupports* aSubject, return NS_OK; } - nsCOMPtr principal; - perm->GetPrincipal(getter_AddRefs(principal)); - if (!principal) { - return NS_OK; - } - - nsCOMPtr 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; } diff --git a/extensions/cookie/nsPermission.cpp b/extensions/cookie/nsPermission.cpp index 9438b0d6643..bdd3abad0e5 100644 --- a/extensions/cookie/nsPermission.cpp +++ b/extensions/cookie/nsPermission.cpp @@ -1,37 +1,51 @@ -/* -*- 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) { - nsCOMPtr copy = mPrincipal; - copy.forget(aPrincipal); + aHost = mHost; + return NS_OK; +} + +NS_IMETHODIMP +nsPermission::GetAppId(uint32_t* aAppId) +{ + *aAppId = mAppId; + return NS_OK; +} + +NS_IMETHODIMP +nsPermission::GetIsInBrowserElement(bool* aIsInBrowserElement) +{ + *aIsInBrowserElement = mIsInBrowserElement; return NS_OK; } @@ -62,117 +76,3 @@ 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 theirURI; - nsresult rv = aPrincipal->GetURI(getter_AddRefs(theirURI)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr 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 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 principal; - nsresult rv = secMan->GetNoAppCodebasePrincipal(aURI, getter_AddRefs(principal)); - NS_ENSURE_SUCCESS(rv, rv); - - return Matches(principal, aExactHost, aMatches); -} diff --git a/extensions/cookie/nsPermission.h b/extensions/cookie/nsPermission.h index 1e966e4b78b..8e459fb59f7 100644 --- a/extensions/cookie/nsPermission.h +++ b/extensions/cookie/nsPermission.h @@ -18,7 +18,9 @@ public: 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, @@ -27,11 +29,13 @@ public: protected: virtual ~nsPermission() {}; - nsCOMPtr mPrincipal; + nsCString mHost; nsCString mType; uint32_t mCapability; uint32_t mExpireType; int64_t mExpireTime; + uint32_t mAppId; + bool mIsInBrowserElement; }; #endif // nsPermission_h__ diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp index ded7500c62d..1364886c36b 100644 --- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -8,7 +8,6 @@ #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentChild.h" -#include "mozilla/BasePrincipal.h" #include "mozilla/unused.h" #include "nsPermissionManager.h" #include "nsPermission.h" @@ -40,8 +39,6 @@ #include "nsReadLine.h" #include "mozilla/Telemetry.h" #include "nsIConsoleService.h" -#include "nsINavHistoryService.h" -#include "nsToolkitCompsCID.h" static nsPermissionManager *gPermissionManager = nullptr; @@ -104,31 +101,29 @@ LogToConsole(const nsAString& aMsg) namespace { nsresult -GetPrincipalFromOrigin(const nsACString& aOrigin, nsIPrincipal** aPrincipal) -{ - nsAutoCString originNoSuffix; - mozilla::OriginAttributes attrs; - if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr 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 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 @@ -140,6 +135,50 @@ GetPrincipal(nsIURI* aURI, nsIPrincipal** aPrincipal) 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 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) { @@ -195,265 +234,6 @@ public: 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 mLookupStmt; - nsCOMPtr mInsertStmt; - nsCOMPtr 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 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("")) { - // We no longer support the magic host - NS_WARNING("The magic host 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 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 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 histSrv = do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID); - - nsCOMPtr 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 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 histResult; - rv = histSrv->ExecuteQuery(histQuery, histQueryOpts, getter_AddRefs(histResult)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr 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 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 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 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 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 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) { @@ -467,7 +247,9 @@ IsExpandedPrincipal(nsIPrincipal* aPrincipal) 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))); } /** @@ -590,7 +372,7 @@ nsPermissionManager::AppClearDataObserverInit() // nsPermissionManager Implementation #define PERMISSIONS_FILE_NAME "permissions.sqlite" -#define HOSTS_SCHEMA_VERSION 5 +#define HOSTS_SCHEMA_VERSION 4 #define HOSTPERM_FILE_NAME "hostperm.1" @@ -833,89 +615,6 @@ nsPermissionManager::InitDB(bool aRemoveFile) // 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 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 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(stmt->AsInt64(6)); - isInBrowserElement = static_cast(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; @@ -931,7 +630,7 @@ nsPermissionManager::InitDB(bool aRemoveFile) // check if all the expected columns exist nsCOMPtr 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; @@ -950,8 +649,8 @@ nsPermissionManager::InitDB(bool aRemoveFile) // 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( @@ -988,12 +687,14 @@ nsPermissionManager::CreateTable() 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" ")")); } @@ -1040,15 +741,6 @@ nsPermissionManager::AddFromPrincipal(nsIPrincipal* 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; @@ -1073,13 +765,21 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, 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 cplist; ContentParent::GetAll(cplist); @@ -1191,11 +891,21 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, 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, @@ -1216,10 +926,12 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, // 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, @@ -1262,10 +974,12 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, // 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, @@ -1316,12 +1030,14 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, 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, @@ -1382,8 +1098,12 @@ nsPermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal, NS_IMETHODIMP nsPermissionManager::RemovePermission(nsIPermission* aPerm) { + nsAutoCString host; + nsresult rv = aPerm->GetHost(host); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr principal; - nsresult rv = aPerm->GetPrincipal(getter_AddRefs(principal)); + rv = GetPrincipal(host, getter_AddRefs(principal)); NS_ENSURE_SUCCESS(rv, rv); nsAutoCString type; @@ -1550,12 +1270,25 @@ nsPermissionManager::GetPermissionObject(nsIPrincipal* 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; } @@ -1567,12 +1300,10 @@ nsPermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal, return NS_OK; } - nsCOMPtr principal; - nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal)); - NS_ENSURE_SUCCESS(rv, rv); - PermissionEntry& perm = entry->GetPermissions()[idx]; - nsCOMPtr r = new nsPermission(principal, + nsCOMPtr r = new nsPermission(entry->GetKey()->mHost, + entry->GetKey()->mAppId, + entry->GetKey()->mIsInBrowserElement, mTypeArray.ElementAt(perm.mType), perm.mPermission, perm.mExpireType, @@ -1624,12 +1355,25 @@ nsPermissionManager::CommonTestPermission(nsIPrincipal* aPrincipal, 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 == @@ -1651,13 +1395,15 @@ nsPermissionManager::CommonTestPermission(nsIPrincipal* aPrincipal, // Also accepts host on the format "". 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 key = new PermissionKey(aPrincipal); + nsRefPtr key = new PermissionKey(aHost, aAppId, aIsInBrowserElement); entry = mPermissionTable.GetEntry(key); if (entry) { @@ -1669,8 +1415,13 @@ nsPermissionManager::GetPermissionHashKey(nsIPrincipal* aPrincipal, (permEntry.mExpireType == nsIPermissionManager::EXPIRE_SESSION && permEntry.mExpireTime != 0)) && permEntry.mExpireTime <= (PR_Now() / 1000)) { + nsCOMPtr 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; } @@ -1680,42 +1431,24 @@ nsPermissionManager::GetPermissionHashKey(nsIPrincipal* aPrincipal, return entry; } - // If aExactHostMatch wasn't true, we can check if the base domain has a permission entry. + // 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 + // 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. + + if (StringBeginsWith(aHost, NS_LITERAL_CSTRING("file://"))) { + return GetPermissionHashKey(NS_LITERAL_CSTRING(""), aAppId, aIsInBrowserElement, aType, true); + } + if (!aExactHostMatch) { - nsCOMPtr uri; - nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); - if (NS_FAILED(rv)) { - return nullptr; + nsCString domain = GetNextSubDomainForHost(aHost); + if (!domain.IsEmpty()) { + return GetPermissionHashKey(domain, aAppId, aIsInBrowserElement, aType, aExactHostMatch); } - - nsAutoCString host; - rv = uri->GetHost(host); - if (NS_FAILED(rv)) { - return nullptr; - } - - nsCString domain = GetNextSubDomainForHost(host); - if (domain.IsEmpty()) { - return nullptr; - } - - // Create a new principal which is identical to the current one, but with the new host - nsCOMPtr 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 principal = mozilla::BasePrincipal::CreateCodebasePrincipal(newURI, attrs); - - return GetPermissionHashKey(principal, aType, aExactHostMatch); } // No entry, really... @@ -1752,10 +1485,9 @@ AddPermissionsToList(nsPermissionManager::PermissionHashKey* entry, void *arg) continue; } - nsCOMPtr 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, @@ -1810,10 +1542,9 @@ AddPermissionsModifiedSinceToList( continue; } - nsCOMPtr 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, @@ -1836,21 +1567,22 @@ nsPermissionManager::RemoveAllModifiedSince(int64_t aModificationTime) mPermissionTable.EnumerateEntries(AddPermissionsModifiedSinceToList, &data); for (int32_t i = 0; i 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 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, @@ -1875,21 +1607,14 @@ nsPermissionManager::GetPermissionsForApp(nsPermissionManager::PermissionHashKey for (uint32_t i = 0; i < entry->GetPermissions().Length(); ++i) { nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i]; - nsCOMPtr 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, @@ -1905,20 +1630,49 @@ 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 removeStmt; + nsresult rv = mDBConn->CreateAsyncStatement(sql, getter_AddRefs(removeStmt)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr 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 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 principal; + if (NS_FAILED(GetPrincipal(host, aAppId, isInBrowserElement, + getter_AddRefs(principal)))) { + NS_ERROR("GetPrincipal() failed!"); + continue; + } + AddInternal(principal, type, nsIPermissionManager::UNKNOWN_ACTION, @@ -1927,7 +1681,7 @@ nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId, bool aBrowserOnly) 0, 0, nsPermissionManager::eNotify, - nsPermissionManager::eWriteToDB); + nsPermissionManager::eNoDBOperation); } return NS_OK; @@ -1937,16 +1691,10 @@ PLDHashOperator nsPermissionManager::RemoveExpiredPermissionsForAppEnumerator( nsPermissionManager::PermissionHashKey* entry, void* arg) { - uint32_t* targetAppId = static_cast(arg); + uint32_t* appId = static_cast(arg); for (uint32_t i = 0; i < entry->GetPermissions().Length(); ++i) { - nsCOMPtr principal; - GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal)); - - uint32_t appId; - principal->GetAppId(&appId); - - if (appId != *targetAppId) { + if (entry->GetKey()->mAppId != *appId) { continue; } @@ -1960,7 +1708,9 @@ nsPermissionManager::RemoveExpiredPermissionsForAppEnumerator( 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, @@ -1974,7 +1724,9 @@ nsPermissionManager::RemoveExpiredPermissionsForAppEnumerator( 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, @@ -2038,7 +1790,9 @@ nsPermissionManager::GetTypeIndex(const char *aType, // 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, @@ -2046,7 +1800,7 @@ nsPermissionManager::NotifyObserversWithPermission(nsIPrincipal* aPrincipal, const char16_t *aData) { nsCOMPtr permission = - new nsPermission(aPrincipal, aType, aPermission, + new nsPermission(aHost, aAppId, aIsInBrowserElement, aType, aPermission, aExpireType, aExpireTime); if (permission) NotifyObservers(permission, aData); @@ -2097,16 +1851,18 @@ nsPermissionManager::Read() nsCOMPtr 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; @@ -2117,7 +1873,7 @@ nsPermissionManager::Read() if (id > mLargestID) mLargestID = id; - rv = stmt->GetUTF8String(1, origin); + rv = stmt->GetUTF8String(1, host); if (NS_FAILED(rv)) { readError = true; continue; @@ -2136,8 +1892,16 @@ nsPermissionManager::Read() expireTime = stmt->AsInt64(5); modificationTime = stmt->AsInt64(6); + if (stmt->AsInt64(7) < 0) { + readError = true; + continue; + } + + appId = static_cast(stmt->AsInt64(7)); + isInBrowserElement = static_cast(stmt->AsInt32(8)); + nsCOMPtr principal; - nsresult rv = GetPrincipalFromOrigin(origin, getter_AddRefs(principal)); + nsresult rv = GetPrincipal(host, appId, isInBrowserElement, getter_AddRefs(principal)); if (NS_FAILED(rv)) { readError = true; continue; @@ -2160,7 +1924,6 @@ nsPermissionManager::Read() } 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 @@ -2270,48 +2033,32 @@ nsPermissionManager::_DoImport(nsIInputStream *inputStream, mozIStorageConnectio 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; - // 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"); + // 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; } - } 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 principal; - error = GetPrincipalFromOrigin(lineArray[3], getter_AddRefs(principal)); - if (NS_FAILED(error)) { - NS_WARNING("Couldn't import an origin permission - malformed origin"); - continue; - } + 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; - 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); @@ -2336,12 +2083,14 @@ 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; @@ -2357,7 +2106,7 @@ nsPermissionManager::UpdateDB(OperationType aOp, 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); @@ -2373,6 +2122,12 @@ nsPermissionManager::UpdateDB(OperationType aOp, 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; } @@ -2491,12 +2246,25 @@ nsPermissionManager::UpdateExpireTime(nsIPrincipal* 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; } @@ -2526,7 +2294,8 @@ nsPermissionManager::FetchPermissions() { const IPC::Permission &perm = perms[i]; nsCOMPtr 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 diff --git a/extensions/cookie/nsPermissionManager.h b/extensions/cookie/nsPermissionManager.h index 7bf2c3d146f..55327005fea 100644 --- a/extensions/cookie/nsPermissionManager.h +++ b/extensions/cookie/nsPermissionManager.h @@ -71,22 +71,35 @@ public: { 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(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. @@ -209,9 +222,11 @@ private: 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, @@ -226,7 +241,9 @@ private: 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, @@ -244,12 +261,14 @@ private: 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); diff --git a/extensions/cookie/test/test_app_uninstall_permissions.html b/extensions/cookie/test/test_app_uninstall_permissions.html index 13cf9f7380b..afb1f1d46c4 100644 --- a/extensions/cookie/test/test_app_uninstall_permissions.html +++ b/extensions/cookie/test/test_app_uninstall_permissions.html @@ -42,7 +42,7 @@ function getPermissionCountForApp(aAppId) { while (enumerator.hasMoreElements()) { var permission = enumerator.getNext().QueryInterface(Ci.nsIPermission); - if (permission.principal.appId == aAppId || aAppId == -1) { + if (permission.appId == aAppId || aAppId == -1) { nbPermissions++; } } diff --git a/extensions/cookie/test/unit/test_permmanager_defaults.js b/extensions/cookie/test/unit/test_permmanager_defaults.js index 65ea18f58b2..7798542edec 100644 --- a/extensions/cookie/test/unit/test_permmanager_defaults.js +++ b/extensions/cookie/test/unit/test_permmanager_defaults.js @@ -2,10 +2,8 @@ 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"); @@ -37,10 +35,8 @@ add_task(function* do_test() { 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. @@ -51,30 +47,14 @@ add_task(function* do_test() { 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); @@ -83,10 +63,6 @@ add_task(function* do_test() { 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 @@ -129,6 +105,9 @@ add_task(function* do_test() { // 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)); @@ -170,12 +149,12 @@ add_task(function* do_test() { // 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! @@ -192,12 +171,12 @@ function findCapabilityViaEnum(origin = TEST_ORIGIN, type = TEST_PERMISSION) { // 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"); @@ -221,10 +200,7 @@ function checkCapabilityViaDB(expected, origin = TEST_ORIGIN, type = TEST_PERMIS // 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"); @@ -234,8 +210,8 @@ function findCapabilityViaDB(origin = TEST_ORIGIN, type = TEST_PERMISSION) { 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()) { diff --git a/extensions/cookie/test/unit/test_permmanager_getPermissionObject.js b/extensions/cookie/test/unit/test_permmanager_getPermissionObject.js index f2f13f38e3a..9ab4ff21f0f 100644 --- a/extensions/cookie/test/unit/test_permmanager_getPermissionObject.js +++ b/extensions/cookie/test/unit/test_permmanager_getPermissionObject.js @@ -29,20 +29,20 @@ function run_test() { 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); @@ -50,7 +50,7 @@ function run_test() { 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); @@ -63,28 +63,28 @@ function run_test() { 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"); diff --git a/extensions/cookie/test/unit/test_permmanager_load_invalid_entries.js b/extensions/cookie/test/unit/test_permmanager_load_invalid_entries.js index 4cb1f960443..b96813b98aa 100644 --- a/extensions/cookie/test/unit/test_permmanager_load_invalid_entries.js +++ b/extensions/cookie/test/unit/test_permmanager_load_invalid_entries.js @@ -121,7 +121,7 @@ function run_test() { // 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; diff --git a/extensions/cookie/test/unit/test_permmanager_local_files.js b/extensions/cookie/test/unit/test_permmanager_local_files.js index 67884cb642c..6de1ce7b063 100644 --- a/extensions/cookie/test/unit/test_permmanager_local_files.js +++ b/extensions/cookie/test/unit/test_permmanager_local_files.js @@ -39,4 +39,10 @@ function run_test() { 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 "" permission and make sure all "file://" now have the permission. + pm.addFromPrincipal(getPrincipalFromURIString("http://"), "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 diff --git a/extensions/cookie/test/unit/test_permmanager_mailto.js b/extensions/cookie/test/unit/test_permmanager_mailto.js new file mode 100644 index 00000000000..21b1f6c60a2 --- /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; +} diff --git a/extensions/cookie/test/unit/test_permmanager_matches.js b/extensions/cookie/test/unit/test_permmanager_matches.js deleted file mode 100644 index 475581aeabd..00000000000 --- 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(); -} diff --git a/extensions/cookie/test/unit/test_permmanager_matchesuri.js b/extensions/cookie/test/unit/test_permmanager_matchesuri.js deleted file mode 100644 index 7317cb35d3a..00000000000 --- 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(); -} diff --git a/extensions/cookie/test/unit/test_permmanager_migrate_4-5.js b/extensions/cookie/test/unit/test_permmanager_migrate_4-5.js deleted file mode 100644 index 253db93dbac..00000000000 --- 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("", "A", 1, 0, 0, 0, 0, false); - insertHost("", "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]); - }); -}); diff --git a/extensions/cookie/test/unit/xpcshell.ini b/extensions/cookie/test/unit/xpcshell.ini index 38ad29f50e1..902d90a992a 100644 --- a/extensions/cookie/test/unit/xpcshell.ini +++ b/extensions/cookie/test/unit/xpcshell.ini @@ -30,10 +30,8 @@ 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] diff --git a/layout/tools/reftest/reftest-preferences.js b/layout/tools/reftest/reftest-preferences.js index 8709d6d37ab..c1a429e629b 100644 --- a/layout/tools/reftest/reftest-preferences.js +++ b/layout/tools/reftest/reftest-preferences.js @@ -65,6 +65,3 @@ // 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); diff --git a/layout/tools/reftest/reftest.js b/layout/tools/reftest/reftest.js index 27daf26b8db..edd61b9cbf2 100644 --- a/layout/tools/reftest/reftest.js +++ b/layout/tools/reftest/reftest.js @@ -1177,9 +1177,6 @@ function ServeFiles(manifestPrincipal, depth, aURL, files) 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 diff --git a/layout/tools/reftest/remotereftest.py b/layout/tools/reftest/remotereftest.py index e7430bade75..c0f5dd1092d 100644 --- a/layout/tools/reftest/remotereftest.py +++ b/layout/tools/reftest/remotereftest.py @@ -342,7 +342,7 @@ class RemoteReftest(RefTest): 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 = {} diff --git a/layout/tools/reftest/runreftest.py b/layout/tools/reftest/runreftest.py index 3d7dd67ea01..09f7c4ad1f6 100644 --- a/layout/tools/reftest/runreftest.py +++ b/layout/tools/reftest/runreftest.py @@ -187,8 +187,8 @@ class RefTest(object): """ 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('', port=0) # Set preferences for communication between our command line arguments # and the reftest harness. Preferences that are required for reftest diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 9e9fabb2b44..8f0e96709e9 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -177,8 +177,8 @@ 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); diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 5e3537f39f5..6df73544b82 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1751,11 +1751,11 @@ var BrowserApp = { 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. @@ -1765,7 +1765,7 @@ var BrowserApp = { // 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); } } diff --git a/netwerk/base/nsIPermission.idl b/netwerk/base/nsIPermission.idl index 1e8a41b76c1..4500679905a 100644 --- a/netwerk/base/nsIPermission.idl +++ b/netwerk/base/nsIPermission.idl @@ -6,10 +6,7 @@ #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 @@ -19,9 +16,19 @@ interface nsIURI; interface nsIPermission : nsISupports { /** - * The principal for which this permission applies. + * The name of the host for which the permission is set */ - readonly attribute nsIPrincipal principal; + readonly attribute AUTF8String host; + + /** + * The id of the app for which the permission is set. + */ + 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 @@ -49,29 +56,4 @@ interface nsIPermission : nsISupports * 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); }; diff --git a/netwerk/ipc/NeckoMessageUtils.h b/netwerk/ipc/NeckoMessageUtils.h index ce0219d21a2..3886a81a8bd 100644 --- a/netwerk/ipc/NeckoMessageUtils.h +++ b/netwerk/ipc/NeckoMessageUtils.h @@ -20,20 +20,26 @@ namespace IPC { 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) {} }; @@ -42,26 +48,34 @@ struct ParamTraits { 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", "); diff --git a/netwerk/test/unit/test_permmgr.js b/netwerk/test/unit/test_permmgr.js index 5a6ddd8b5a1..f472770a5f7 100644 --- a/netwerk/test/unit/test_permmgr.js +++ b/netwerk/test/unit/test_permmgr.js @@ -2,31 +2,31 @@ 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() { @@ -45,16 +45,16 @@ function run_test() { // 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]); @@ -72,13 +72,16 @@ function run_test() { // ... 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); @@ -99,7 +102,7 @@ function run_test() { 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() diff --git a/testing/mozbase/mozprofile/mozprofile/permissions.py b/testing/mozbase/mozprofile/mozprofile/permissions.py index 56bfa18b57a..126d0f91f99 100644 --- a/testing/mozbase/mozprofile/mozprofile/permissions.py +++ b/testing/mozbase/mozprofile/mozprofile/permissions.py @@ -231,26 +231,18 @@ class Permissions(object): # 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 @@ -270,26 +262,8 @@ class Permissions(object): 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() diff --git a/testing/mozbase/mozprofile/tests/bug785146.py b/testing/mozbase/mozprofile/tests/bug785146.py index 629a81523ab..26b98ffc0c4 100755 --- a/testing/mozbase/mozprofile/tests/bug785146.py +++ b/testing/mozbase/mozprofile/tests/bug785146.py @@ -44,7 +44,7 @@ http://127.0.0.1:8888 privileged entries = cur.fetchall() schema_version = entries[0][0] - self.assertEqual(schema_version, 5) + self.assertEqual(schema_version, 2) if __name__ == '__main__': unittest.main() diff --git a/testing/mozbase/mozprofile/tests/permissions.py b/testing/mozbase/mozprofile/tests/permissions.py index 389f14a5c8a..b402991d929 100755 --- a/testing/mozbase/mozprofile/tests/permissions.py +++ b/testing/mozbase/mozprofile/tests/permissions.py @@ -40,16 +40,7 @@ http://127.0.0.1:8888 privileged 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, @@ -79,7 +70,7 @@ http://127.0.0.1:8888 privileged 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() @@ -88,7 +79,7 @@ http://127.0.0.1:8888 privileged 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() @@ -97,32 +88,32 @@ http://127.0.0.1:8888 privileged 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 @@ -169,14 +160,7 @@ http://127.0.0.1:8888 privileged 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) @@ -190,8 +174,5 @@ http://127.0.0.1:8888 privileged 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() diff --git a/testing/specialpowers/components/SpecialPowersObserver.js b/testing/specialpowers/components/SpecialPowersObserver.js index 10703da4a62..95f51445540 100644 --- a/testing/specialpowers/components/SpecialPowersObserver.js +++ b/testing/specialpowers/components/SpecialPowersObserver.js @@ -217,16 +217,7 @@ SpecialPowersObserver.prototype = new SpecialPowersObserverAPI(); 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); } diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/specialpowers/content/specialpowersAPI.js index 6a01c635c29..59cd60b415e 100644 --- a/testing/specialpowers/content/specialpowersAPI.js +++ b/testing/specialpowers/content/specialpowersAPI.js @@ -967,7 +967,7 @@ SpecialPowersAPI.prototype = { 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.) diff --git a/toolkit/forgetaboutsite/ForgetAboutSite.jsm b/toolkit/forgetaboutsite/ForgetAboutSite.jsm index ad9f5a46370..9e9e65298d9 100644 --- a/toolkit/forgetaboutsite/ForgetAboutSite.jsm +++ b/toolkit/forgetaboutsite/ForgetAboutSite.jsm @@ -140,13 +140,8 @@ this.ForgetAboutSite = { 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 diff --git a/toolkit/modules/BrowserUtils.jsm b/toolkit/modules/BrowserUtils.jsm index 4f17f4b879b..412e574214e 100644 --- a/toolkit/modules/BrowserUtils.jsm +++ b/toolkit/modules/BrowserUtils.jsm @@ -105,7 +105,7 @@ this.BrowserUtils = { 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); } diff --git a/toolkit/modules/PermissionsUtils.jsm b/toolkit/modules/PermissionsUtils.jsm index ec04826959c..37e7abb5b15 100644 --- a/toolkit/modules/PermissionsUtils.jsm +++ b/toolkit/modules/PermissionsUtils.jsm @@ -7,7 +7,6 @@ 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(); @@ -16,40 +15,29 @@ 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, ""); diff --git a/toolkit/modules/tests/xpcshell/test_PermissionsUtils.js b/toolkit/modules/tests/xpcshell/test_PermissionsUtils.js index 48769f83123..a3bf2fa4afa 100644 --- a/toolkit/modules/tests/xpcshell/test_PermissionsUtils.js +++ b/toolkit/modules/tests/xpcshell/test_PermissionsUtils.js @@ -23,36 +23,22 @@ 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); @@ -78,8 +64,4 @@ function test_importfromPrefs() { 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); - } } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js index eb8bc3e5c91..869b7bdc1ee 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js @@ -12,9 +12,9 @@ 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); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js b/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js index d3eb5ca02f7..75c615ace00 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js @@ -30,9 +30,9 @@ function run_test() { // 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, {}); @@ -53,19 +53,19 @@ function run_test() { // 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"); }