Bug 1173523 - Part 4: Update about:permissions to use new API for nsIPermission, r=margaret

This commit is contained in:
Michael Layzell 2015-06-02 11:24:42 -04:00 коммит произвёл Ehsan Akhgari
Родитель 47b0919e97
Коммит 5482e7b53e
3 изменённых файлов: 82 добавлений и 80 удалений

Просмотреть файл

@ -17,6 +17,9 @@ Cu.import("resource://gre/modules/ForgetAboutSite.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm"); "resource://gre/modules/PluralForm.jsm");
let gSecMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager);
let gFaviconService = Cc["@mozilla.org/browser/favicon-service;1"]. let gFaviconService = Cc["@mozilla.org/browser/favicon-service;1"].
getService(Ci.nsIFaviconService); getService(Ci.nsIFaviconService);
@ -26,7 +29,7 @@ let gPlacesDatabase = Cc["@mozilla.org/browser/nav-history-service;1"].
clone(true); clone(true);
let gSitesStmt = gPlacesDatabase.createAsyncStatement( let gSitesStmt = gPlacesDatabase.createAsyncStatement(
"SELECT get_unreversed_host(rev_host) AS host " + "SELECT url " +
"FROM moz_places " + "FROM moz_places " +
"WHERE rev_host > '.' " + "WHERE rev_host > '.' " +
"AND visit_count > 0 " + "AND visit_count > 0 " +
@ -46,14 +49,11 @@ let gVisitStmt = gPlacesDatabase.createAsyncStatement(
let TEST_EXACT_PERM_TYPES = ["geo", "camera", "microphone"]; let TEST_EXACT_PERM_TYPES = ["geo", "camera", "microphone"];
/** /**
* Site object represents a single site, uniquely identified by a host. * Site object represents a single site, uniquely identified by a principal.
*/ */
function Site(host) { function Site(principal) {
this.host = host; this.principal = principal;
this.listitem = null; this.listitem = null;
this.httpURI = NetUtil.newURI("http://" + this.host);
this.httpsURI = NetUtil.newURI("https://" + this.host);
} }
Site.prototype = { Site.prototype = {
@ -75,16 +75,10 @@ Site.prototype = {
} }
} }
// Try to find favicon for both URIs, but always prefer the https favicon. // Get the favicon for the origin
gFaviconService.getFaviconURLForPage(this.httpsURI, function (aURI) { gFaviconService.getFaviconURLForPage(this.principal.URI, function (aURI) {
if (aURI) { if (aURI) {
invokeCallback(aURI); invokeCallback(aURI);
} else {
gFaviconService.getFaviconURLForPage(this.httpURI, function (aURI) {
if (aURI) {
invokeCallback(aURI);
}
});
} }
}.bind(this)); }.bind(this));
}, },
@ -96,7 +90,9 @@ Site.prototype = {
* A function that takes the visit count (a number) as a parameter. * A function that takes the visit count (a number) as a parameter.
*/ */
getVisitCount: function Site_getVisitCount(aCallback) { getVisitCount: function Site_getVisitCount(aCallback) {
let rev_host = this.host.split("").reverse().join("") + "."; // 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("") + ".";
gVisitStmt.params.rev_host = rev_host; gVisitStmt.params.rev_host = rev_host;
gVisitStmt.executeAsync({ gVisitStmt.executeAsync({
handleResult: function(aResults) { handleResult: function(aResults) {
@ -139,9 +135,9 @@ Site.prototype = {
let permissionValue; let permissionValue;
if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) { if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) {
permissionValue = Services.perms.testPermission(this.httpURI, aType); permissionValue = Services.perms.testPermissionFromPrincipal(this.principal, aType);
} else { } else {
permissionValue = Services.perms.testExactPermission(this.httpURI, aType); permissionValue = Services.perms.testExactPermissionFromPrincipal(this.principal, aType);
} }
aResultObj.value = permissionValue; aResultObj.value = permissionValue;
@ -166,9 +162,7 @@ Site.prototype = {
return; return;
} }
// Using httpURI is kind of bogus, but the permission manager stores the Services.perms.addFromPrincipal(this.principal, aType, aPerm);
// permission for the host, so the right thing happens in the end.
Services.perms.add(this.httpURI, aType, aPerm);
}, },
/** /**
@ -179,7 +173,7 @@ Site.prototype = {
* e.g. "cookie", "geo", "indexedDB", "popup", "image" * e.g. "cookie", "geo", "indexedDB", "popup", "image"
*/ */
clearPermission: function Site_clearPermission(aType) { clearPermission: function Site_clearPermission(aType) {
Services.perms.remove(this.httpURI, aType); Services.perms.removeFromPrincipal(this.principal, aType);
}, },
/** /**
@ -189,13 +183,14 @@ Site.prototype = {
* @return An array of the cookies set for the site. * @return An array of the cookies set for the site.
*/ */
get cookies() { get cookies() {
let host = this.principal.URI.host;
let cookies = []; let cookies = [];
let enumerator = Services.cookies.getCookiesFromHost(this.host); let enumerator = Services.cookies.getCookiesFromHost(host);
while (enumerator.hasMoreElements()) { while (enumerator.hasMoreElements()) {
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2); let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
// getCookiesFromHost returns cookies for base domain, but we only want // getCookiesFromHost returns cookies for base domain, but we only want
// the cookies for the exact domain. // the cookies for the exact domain.
if (cookie.rawHost == this.host) { if (cookie.rawHost == host) {
cookies.push(cookie); cookies.push(cookie);
} }
} }
@ -217,27 +212,27 @@ Site.prototype = {
* @return An array of the logins stored for the site. * @return An array of the logins stored for the site.
*/ */
get logins() { get logins() {
let httpLogins = Services.logins.findLogins({}, this.httpURI.prePath, "", ""); let logins = Services.logins.findLogins({}, this.principal.originNoSuffix, "", "");
let httpsLogins = Services.logins.findLogins({}, this.httpsURI.prePath, "", ""); return logins;
return httpLogins.concat(httpsLogins);
}, },
get loginSavingEnabled() { get loginSavingEnabled() {
// Only say that login saving is blocked if it is blocked for both http and https. return Services.logins.getLoginSavingEnabled(this.principal.originNoSuffix);
return Services.logins.getLoginSavingEnabled(this.httpURI.prePath) &&
Services.logins.getLoginSavingEnabled(this.httpsURI.prePath);
}, },
set loginSavingEnabled(isEnabled) { set loginSavingEnabled(isEnabled) {
Services.logins.setLoginSavingEnabled(this.httpURI.prePath, isEnabled); Services.logins.setLoginSavingEnabled(this.principal.originNoSuffix, isEnabled);
Services.logins.setLoginSavingEnabled(this.httpsURI.prePath, isEnabled);
}, },
/** /**
* Removes all data from the browser corresponding to the site. * Removes all data from the browser corresponding to the site.
*/ */
forgetSite: function Site_forgetSite() { forgetSite: function Site_forgetSite() {
ForgetAboutSite.removeDataFromDomain(this.host); // 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);
} }
} }
@ -366,7 +361,7 @@ let AboutPermissions = {
LIST_BUILD_DELAY: 100, // delay between intervals LIST_BUILD_DELAY: 100, // delay between intervals
/** /**
* Stores a mapping of host strings to Site objects. * Stores a mapping of origin strings to Site objects.
*/ */
_sites: {}, _sites: {},
@ -472,9 +467,9 @@ let AboutPermissions = {
break; break;
} }
let permission = aSubject.QueryInterface(Ci.nsIPermission); let permission = aSubject.QueryInterface(Ci.nsIPermission);
// We can't compare selectedSite.host and permission.host here because // We can't compare selectedSite.principal and permission.principal here
// we need to handle the case where a parent domain was changed in a // because we need to handle the case where a parent domain was changed
// way that affects the subdomain. // in a way that affects the subdomain.
if (this._supportedPermissions.indexOf(permission.type) != -1) { if (this._supportedPermissions.indexOf(permission.type) != -1) {
this.updatePermission(permission.type); this.updatePermission(permission.type);
} }
@ -512,8 +507,11 @@ let AboutPermissions = {
AboutPermissions.startSitesListBatch(); AboutPermissions.startSitesListBatch();
let row; let row;
while (row = aResults.getNextRow()) { while (row = aResults.getNextRow()) {
let host = row.getResultByName("host"); let spec = row.getResultByName("url");
AboutPermissions.addHost(host); let uri = NetUtil.newURI(spec);
let principal = gSecMan.getNoAppCodebasePrincipal(uri);
AboutPermissions.addPrincipal(principal);
} }
AboutPermissions.endSitesListBatch(); AboutPermissions.endSitesListBatch();
}, },
@ -562,7 +560,8 @@ let AboutPermissions = {
try { try {
// aLogin.hostname is a string in origin URL format (e.g. "http://foo.com") // aLogin.hostname is a string in origin URL format (e.g. "http://foo.com")
let uri = NetUtil.newURI(aLogin.hostname); let uri = NetUtil.newURI(aLogin.hostname);
this.addHost(uri.host); let principal = gSecMan.getNoAppCodebasePrincipal(uri);
this.addPrincipal(principal);
} catch (e) { } catch (e) {
// newURI will throw for add-ons logins stored in chrome:// URIs // newURI will throw for add-ons logins stored in chrome:// URIs
} }
@ -577,7 +576,8 @@ let AboutPermissions = {
try { try {
// aHostname is a string in origin URL format (e.g. "http://foo.com") // aHostname is a string in origin URL format (e.g. "http://foo.com")
let uri = NetUtil.newURI(aHostname); let uri = NetUtil.newURI(aHostname);
this.addHost(uri.host); let principal = gSecMan.getNoAppCodebasePrincipal(uri);
this.addPrincipal(principal);
} catch (e) { } catch (e) {
// newURI will throw for add-ons logins stored in chrome:// URIs // newURI will throw for add-ons logins stored in chrome:// URIs
} }
@ -592,7 +592,7 @@ let AboutPermissions = {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission); let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
// Only include sites with exceptions set for supported permission types. // Only include sites with exceptions set for supported permission types.
if (this._supportedPermissions.indexOf(permission.type) != -1) { if (this._supportedPermissions.indexOf(permission.type) != -1) {
this.addHost(permission.host); this.addPrincipal(permission.principal);
} }
itemCnt++; itemCnt++;
} }
@ -603,15 +603,15 @@ let AboutPermissions = {
/** /**
* Creates a new Site and adds it to _sites if it's not already there. * Creates a new Site and adds it to _sites if it's not already there.
* *
* @param aHost * @param aPrincipal
* A host string. * A principal.
*/ */
addHost: function(aHost) { addPrincipal: function(aPrincipal) {
if (aHost in this._sites) { if (aPrincipal.origin in this._sites) {
return; return;
} }
let site = new Site(aHost); let site = new Site(aPrincipal);
this._sites[aHost] = site; this._sites[aPrincipal.origin] = site;
this.addToSitesList(site); this.addToSitesList(site);
}, },
@ -624,7 +624,7 @@ let AboutPermissions = {
addToSitesList: function(aSite) { addToSitesList: function(aSite) {
let item = document.createElement("richlistitem"); let item = document.createElement("richlistitem");
item.setAttribute("class", "site"); item.setAttribute("class", "site");
item.setAttribute("value", aSite.host); item.setAttribute("value", aSite.principal.origin);
aSite.getFavicon(function(aURL) { aSite.getFavicon(function(aURL) {
item.setAttribute("favicon", aURL); item.setAttribute("favicon", aURL);
@ -633,7 +633,7 @@ let AboutPermissions = {
// Make sure to only display relevant items when list is filtered // Make sure to only display relevant items when list is filtered
let filterValue = document.getElementById("sites-filter").value.toLowerCase(); let filterValue = document.getElementById("sites-filter").value.toLowerCase();
item.collapsed = aSite.host.toLowerCase().indexOf(filterValue) == -1; item.collapsed = aSite.principal.origin.toLowerCase().indexOf(filterValue) == -1;
(this._listFragment || this.sitesList).appendChild(item); (this._listFragment || this.sitesList).appendChild(item);
}, },
@ -686,16 +686,16 @@ let AboutPermissions = {
* The host string corresponding to the site to delete. * The host string corresponding to the site to delete.
*/ */
deleteFromSitesList: function(aHost) { deleteFromSitesList: function(aHost) {
for (let host in this._sites) { for (let origin in this._sites) {
let site = this._sites[host]; let site = this._sites[origin];
if (site.host.hasRootDomain(aHost)) { if (site.principal.URI.host.hasRootDomain(aHost)) {
if (site == this._selectedSite) { if (site == this._selectedSite) {
// Replace site-specific interface with "All Sites" interface. // Replace site-specific interface with "All Sites" interface.
this.sitesList.selectedItem = document.getElementById("all-sites-item"); this.sitesList.selectedItem = document.getElementById("all-sites-item");
} }
this.sitesList.removeChild(site.listitem); this.sitesList.removeChild(site.listitem);
delete this._sites[site.host]; delete this._sites[site.principal.origin];
} }
} }
}, },
@ -711,9 +711,9 @@ let AboutPermissions = {
return; return;
} }
let host = event.target.value; let origin = event.target.value;
let site = this._selectedSite = this._sites[host]; let site = this._selectedSite = this._sites[origin];
document.getElementById("site-label").value = host; document.getElementById("site-label").value = origin;
document.getElementById("header-deck").selectedPanel = document.getElementById("header-deck").selectedPanel =
document.getElementById("site-header"); document.getElementById("site-header");
@ -768,9 +768,9 @@ let AboutPermissions = {
// If there is no selected site, we are updating the default permissions interface. // If there is no selected site, we are updating the default permissions interface.
permissionValue = PermissionDefaults[aType]; permissionValue = PermissionDefaults[aType];
if (aType == "cookie") if (aType == "cookie")
// cookie-9 corresponds to ALLOW_FIRST_PARTY_ONLY, which is reserved // cookie-9 corresponds to ALLOW_FIRST_PARTY_ONLY, which is reserved
// for site-specific preferences only. // for site-specific preferences only.
document.getElementById("cookie-9").hidden = true; document.getElementById("cookie-9").hidden = true;
} else { } else {
if (aType == "cookie") if (aType == "cookie")
document.getElementById("cookie-9").hidden = false; document.getElementById("cookie-9").hidden = false;
@ -825,18 +825,18 @@ let AboutPermissions = {
* Opens password manager dialog. * Opens password manager dialog.
*/ */
managePasswords: function() { managePasswords: function() {
let selectedHost = ""; let selectedOrigin = "";
if (this._selectedSite) { if (this._selectedSite) {
selectedHost = this._selectedSite.host; selectedOrigin = this._selectedSite.principal.URI.prePath;
} }
let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager"); let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager");
if (win) { if (win) {
win.setFilter(selectedHost); win.setFilter(selectedOrigin);
win.focus(); win.focus();
} else { } else {
window.openDialog("chrome://passwordmgr/content/passwordManager.xul", window.openDialog("chrome://passwordmgr/content/passwordManager.xul",
"Toolkit:PasswordManager", "", {filterString : selectedHost}); "Toolkit:PasswordManager", "", {filterString : selectedOrigin});
} }
}, },
@ -877,9 +877,11 @@ let AboutPermissions = {
* Opens cookie manager dialog. * Opens cookie manager dialog.
*/ */
manageCookies: function() { 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 = ""; let selectedHost = "";
if (this._selectedSite) { if (this._selectedSite) {
selectedHost = this._selectedSite.host; selectedHost = this._selectedSite.principal.URI.host;
} }
let win = Services.wm.getMostRecentWindow("Browser:Cookies"); let win = Services.wm.getMostRecentWindow("Browser:Cookies");

Просмотреть файл

@ -103,11 +103,11 @@ var tests = [
sitesFilter.doCommand(); sitesFilter.doCommand();
}, },
run: function() { run: function() {
let testSite1 = getSiteItem(TEST_URI_1.host); let testSite1 = getSiteItem(TEST_URI_1.prePath);
ok(testSite1.collapsed, "test site 1 is collapsed after early filtering"); ok(testSite1.collapsed, "test site 1 is collapsed after early filtering");
let testSite2 = getSiteItem(TEST_URI_2.host); let testSite2 = getSiteItem(TEST_URI_2.prePath);
ok(!testSite2.collapsed, "test site 2 is not collapsed after early filtering"); ok(!testSite2.collapsed, "test site 2 is not collapsed after early filtering");
let testSite3 = getSiteItem(TEST_URI_3.host); let testSite3 = getSiteItem(TEST_URI_3.prePath);
ok(testSite3.collapsed, "test site 3 is collapsed after early filtering"); ok(testSite3.collapsed, "test site 3 is collapsed after early filtering");
runNextTest(); runNextTest();
@ -119,11 +119,11 @@ var tests = [
ForgetAboutSite.removeDataFromDomain(TEST_URI_2.host); ForgetAboutSite.removeDataFromDomain(TEST_URI_2.host);
}, },
run: function() { run: function() {
let testSite1 = getSiteItem(TEST_URI_1.host); let testSite1 = getSiteItem(TEST_URI_1.prePath);
ok(testSite1, "test site 1 was not removed from sites list"); ok(testSite1, "test site 1 was not removed from sites list");
let testSite2 = getSiteItem(TEST_URI_2.host); let testSite2 = getSiteItem(TEST_URI_2.prePath);
ok(!testSite2, "test site 2 was pre-removed from sites list"); ok(!testSite2, "test site 2 was pre-removed from sites list");
let testSite3 = getSiteItem(TEST_URI_3.host); let testSite3 = getSiteItem(TEST_URI_3.prePath);
ok(testSite3, "test site 3 was not removed from sites list"); ok(testSite3, "test site 3 was not removed from sites list");
runNextTest(); runNextTest();
@ -131,7 +131,7 @@ var tests = [
} }
]; ];
function getSiteItem(aHost) { function getSiteItem(aPrePath) {
return gBrowser.contentDocument. return gBrowser.contentDocument.
querySelector(".site[value='" + aHost + "']"); querySelector(".site[value='" + aPrePath + "']");
} }

Просмотреть файл

@ -115,8 +115,8 @@ var tests = [
is(gSitesList.firstChild.id, "all-sites-item", is(gSitesList.firstChild.id, "all-sites-item",
"all sites is the first item in the sites list"); "all sites is the first item in the sites list");
ok(getSiteItem(TEST_URI_1.host), "site item from places db exists"); ok(getSiteItem(TEST_URI_1.prePath), "site item from places db exists");
ok(getSiteItem(TEST_URI_2.host), "site item from enumerating services exists"); ok(getSiteItem(TEST_URI_2.prePath), "site item from enumerating services exists");
runNextTest(); runNextTest();
}, },
@ -128,9 +128,9 @@ var tests = [
sitesFilter.doCommand(); sitesFilter.doCommand();
// make sure correct sites are collapsed/showing // make sure correct sites are collapsed/showing
let testSite1 = getSiteItem(TEST_URI_1.host); let testSite1 = getSiteItem(TEST_URI_1.prePath);
ok(!testSite1.collapsed, "test site 1 is not collapsed"); ok(!testSite1.collapsed, "test site 1 is not collapsed");
let testSite2 = getSiteItem(TEST_URI_2.host); let testSite2 = getSiteItem(TEST_URI_2.prePath);
ok(testSite2.collapsed, "test site 2 is collapsed"); ok(testSite2.collapsed, "test site 2 is collapsed");
// clear filter // clear filter
@ -202,13 +202,13 @@ var tests = [
function test_select_site() { function test_select_site() {
// select the site that has the permissions we set at the beginning of the test // select the site that has the permissions we set at the beginning of the test
let testSiteItem = getSiteItem(TEST_URI_2.host); let testSiteItem = getSiteItem(TEST_URI_2.prePath);
gSitesList.selectedItem = testSiteItem; gSitesList.selectedItem = testSiteItem;
let siteHeader = gBrowser.contentDocument.getElementById("site-header"); let siteHeader = gBrowser.contentDocument.getElementById("site-header");
is(siteHeader, gHeaderDeck.selectedPanel, is(siteHeader, gHeaderDeck.selectedPanel,
"correct header shown for a specific site"); "correct header shown for a specific site");
is(gSiteLabel.value, TEST_URI_2.host, "header updated for selected site"); is(gSiteLabel.value, TEST_URI_2.prePath, "header updated for selected site");
ok(!gBrowser.contentDocument.getElementById("passwords-count").hidden, ok(!gBrowser.contentDocument.getElementById("passwords-count").hidden,
"passwords count is not hidden"); "passwords count is not hidden");
@ -283,7 +283,7 @@ var tests = [
"all sites item selected after forgetting selected site"); "all sites item selected after forgetting selected site");
// check to make sure site is gone from sites list // check to make sure site is gone from sites list
let testSiteItem = getSiteItem(TEST_URI_2.host); let testSiteItem = getSiteItem(TEST_URI_2.prePath);
ok(!testSiteItem, "site removed from sites list"); ok(!testSiteItem, "site removed from sites list");
// check to make sure we forgot all permissions corresponding to site // check to make sure we forgot all permissions corresponding to site