# HG changeset patch # User Johann Hofmann # Date 1518131043 -3600 # Node ID 7fe3e62d6413a53e1ee4522b48a63af799b7acdb # Parent 2a801dbadfdb6c471be433d7bdf61875e5391c6e Bug 1421737 - Part 4 - Update site data manager tests to include cookies. r=Gijs This adds a dedicated test for showing and deleting cookies in site data management as well as amending tests for sorting, grouping, etc. MozReview-Commit-ID: 59mN3uASwPP diff --git a/browser/components/preferences/in-content-new/tests/browser_siteData.js b/browser/components/preferences/in-content-new/tests/browser_siteData.js --- a/browser/components/preferences/in-content-new/tests/browser_siteData.js +++ b/browser/components/preferences/in-content-new/tests/browser_siteData.js @@ -5,16 +5,17 @@ const TEST_QUOTA_USAGE_HOST = "example.com"; const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST; const TEST_QUOTA_USAGE_URL = TEST_QUOTA_USAGE_ORIGIN + "/browser/browser/components/preferences/in-content-new/tests/site_data_test.html"; const TEST_OFFLINE_HOST = "example.org"; const TEST_OFFLINE_ORIGIN = "https://" + TEST_OFFLINE_HOST; const TEST_OFFLINE_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content-new/tests/offline/offline.html"; const TEST_SERVICE_WORKER_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content-new/tests/service_worker_test.html"; +const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul"; const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm", {}); const { DownloadUtils } = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm", {}); const { SiteDataManager } = ChromeUtils.import("resource:///modules/SiteDataManager.jsm", {}); const { OfflineAppCacheHelper } = ChromeUtils.import("resource:///modules/offlineAppCache.jsm", {}); function getPersistentStoragePermStatus(origin) { let uri = NetUtil.newURI(origin); @@ -160,8 +161,99 @@ add_task(async function() { } }); await acceptRemovePromise; await updatePromise; await promiseServiceWorkersCleared(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); +// Test showing and removing sites with cookies. +add_task(async function() { + SiteDataManager.removeAll(); + + // Add some test cookies. + let uri = Services.io.newURI("https://example.com"); + let uri2 = Services.io.newURI("https://example.org"); + Services.cookies.add(uri.host, uri.path, "test1", "1", + false, false, false, Date.now() + 1000 * 60 * 60); + Services.cookies.add(uri.host, uri.path, "test2", "2", + false, false, false, Date.now() + 1000 * 60 * 60); + Services.cookies.add(uri2.host, uri2.path, "test1", "1", + false, false, false, Date.now() + 1000 * 60 * 60); + + // Ensure that private browsing cookies are ignored. + Services.cookies.add(uri.host, uri.path, "test3", "3", + false, false, false, Date.now() + 1000 * 60 * 60, { privateBrowsingId: 1 }); + + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + + // Open the site data manager and remove one site. + await openSiteDataSettingsDialog(); + let removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL); + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + let frameDoc = content.gSubDialog._topDialog._frame.contentDocument; + + let siteItems = frameDoc.getElementsByTagName("richlistitem"); + is(siteItems.length, 2, "Should list two sites with cookies"); + let sitesList = frameDoc.getElementById("sitesList"); + let site1 = sitesList.querySelector(`richlistitem[host="example.com"]`); + let site2 = sitesList.querySelector(`richlistitem[host="example.org"]`); + + let columns = site1.querySelectorAll(".item-box > label"); + is(columns[0].value, "example.com", "Should show the correct host."); + is(columns[2].value, "2", "Should show the correct number of cookies."); + is(columns[3].value, "", "Should show no site data."); + + columns = site2.querySelectorAll(".item-box > label"); + is(columns[0].value, "example.org", "Should show the correct host."); + is(columns[2].value, "1", "Should show the correct number of cookies."); + is(columns[3].value, "", "Should show no site data."); + + let removeBtn = frameDoc.getElementById("removeSelected"); + let saveBtn = frameDoc.getElementById("save"); + site2.click(); + removeBtn.doCommand(); + saveBtn.doCommand(); + }); + await removeDialogOpenPromise; + + await TestUtils.waitForCondition(() => Services.cookies.countCookiesFromHost(uri2.host) == 0, "Cookies from the first host should be cleared"); + is(Services.cookies.countCookiesFromHost(uri.host), 2, "Cookies from the second host should not be cleared"); + + // Open the site data manager and remove another site. + await openSiteDataSettingsDialog(); + let acceptRemovePromise = promiseAlertDialogOpen("accept"); + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + let frameDoc = content.gSubDialog._topDialog._frame.contentDocument; + + let siteItems = frameDoc.getElementsByTagName("richlistitem"); + is(siteItems.length, 1, "Should list one site with cookies"); + let sitesList = frameDoc.getElementById("sitesList"); + let site1 = sitesList.querySelector(`richlistitem[host="example.com"]`); + + let columns = site1.querySelectorAll(".item-box > label"); + is(columns[0].value, "example.com", "Should show the correct host."); + is(columns[2].value, "2", "Should show the correct number of cookies."); + is(columns[3].value, "", "Should show no site data."); + + let removeBtn = frameDoc.getElementById("removeSelected"); + let saveBtn = frameDoc.getElementById("save"); + site1.click(); + removeBtn.doCommand(); + saveBtn.doCommand(); + }); + await acceptRemovePromise; + + await TestUtils.waitForCondition(() => Services.cookies.countCookiesFromHost(uri.host) == 0, "Cookies from the second host should be cleared"); + + await openSiteDataSettingsDialog(); + + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + let frameDoc = content.gSubDialog._topDialog._frame.contentDocument; + + let siteItems = frameDoc.getElementsByTagName("richlistitem"); + is(siteItems.length, 0, "Should list no sites with cookies"); + }); + + await BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + diff --git a/browser/components/preferences/in-content-new/tests/browser_siteData2.js b/browser/components/preferences/in-content-new/tests/browser_siteData2.js --- a/browser/components/preferences/in-content-new/tests/browser_siteData2.js +++ b/browser/components/preferences/in-content-new/tests/browser_siteData2.js @@ -26,43 +26,38 @@ function assertAllSitesNotListed(win) { is(sites.length, 0, "Should not list all sites"); is(removeBtn.disabled, true, "Should disable the removeSelected button"); is(removeAllBtn.disabled, true, "Should disable the removeAllBtn button"); } // Test selecting and removing all sites one by one add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); let win = gBrowser.selectedBrowser.contentWindow; @@ -86,20 +81,22 @@ add_task(async function() { await openSiteDataSettingsDialog(); assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button but cancelling save let cancelPromise = promiseAlertDialogOpen("cancel"); settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; saveBtn = frameDoc.getElementById("save"); + cancelBtn = frameDoc.getElementById("cancel"); removeAllSitesOneByOne(); assertAllSitesNotListed(win); saveBtn.doCommand(); await cancelPromise; + cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button and accepting save let acceptPromise = promiseAlertDialogOpen("accept"); settingsDialogClosePromise = promiseSettingsDialogClose(); updatePromise = promiseSiteDataManagerSitesUpdated(); @@ -127,61 +124,53 @@ add_task(async function() { removeBtn.doCommand(); } } }); // Test selecting and removing partial sites add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://s3-us-west-2.amazonaws.com"), + origin: "https://s3-us-west-2.amazonaws.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://127.0.0.1"), + origin: "https://127.0.0.1", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://[0:0:0:0:0:0:0:1]"), + origin: "https://[0:0:0:0:0:0:0:1]", persisted: true }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); let win = gBrowser.selectedBrowser.contentWindow; @@ -206,20 +195,22 @@ add_task(async function() { await openSiteDataSettingsDialog(); assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button but canceling save removeDialogOpenPromise = promiseWindowDialogOpen("cancel", REMOVE_DIALOG_URL); settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; saveBtn = frameDoc.getElementById("save"); + cancelBtn = frameDoc.getElementById("cancel"); removeSelectedSite(fakeHosts.slice(0, 2)); assertSitesListed(doc, fakeHosts.slice(2)); saveBtn.doCommand(); await removeDialogOpenPromise; + cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button and accepting save removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL); settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; @@ -251,43 +242,38 @@ add_task(async function() { } }); } }); // Test searching and then removing only visible sites add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); // Search "foo" to only list foo.com sites @@ -315,31 +301,28 @@ add_task(async function() { mockSiteDataManager.unregister(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test dynamically clearing all site data add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); // Test the initial state let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); let doc = gBrowser.selectedBrowser.contentDocument; diff --git a/browser/components/preferences/in-content-new/tests/browser_siteData3.js b/browser/components/preferences/in-content-new/tests/browser_siteData3.js --- a/browser/components/preferences/in-content-new/tests/browser_siteData3.js +++ b/browser/components/preferences/in-content-new/tests/browser_siteData3.js @@ -1,42 +1,43 @@ "use strict"; const { SiteDataManager } = Cu.import("resource:///modules/SiteDataManager.jsm", {}); const { DownloadUtils } = Cu.import("resource://gre/modules/DownloadUtils.jsm", {}); // Test not displaying sites which store 0 byte and don't have persistent storage. add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register(SiteDataManager, [ { usage: 0, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 0, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, - ]; + { + usage: 0, + origin: "http://cookies.bar.com", + cookies: 5, + persisted: false + }, + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); let doc = gBrowser.selectedBrowser.contentDocument; await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); assertSitesListed(doc, fakeHosts.filter(host => host != "shopping.xyz.com")); @@ -44,141 +45,149 @@ add_task(async function() { mockSiteDataManager.unregister(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test grouping and listing sites across scheme, port and origin attributes by host add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); const quotaUsage = 1024; - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register(SiteDataManager, [ { usage: quotaUsage, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com^userContextId=1"), + origin: "https://account.xyz.com^userContextId=1", + cookies: 2, persisted: true }, { usage: quotaUsage, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", + cookies: 1, persisted: false }, { usage: quotaUsage, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com:123"), + origin: "https://account.xyz.com:123", + cookies: 1, persisted: false }, { usage: quotaUsage, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://account.xyz.com"), + origin: "http://account.xyz.com", + cookies: 1, persisted: false }, - ]; + ]); let updatedPromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatedPromise; await openSiteDataSettingsDialog(); let win = gBrowser.selectedBrowser.contentWindow; let dialogFrame = win.gSubDialog._topDialog._frame; let frameDoc = dialogFrame.contentDocument; let siteItems = frameDoc.getElementsByTagName("richlistitem"); is(siteItems.length, 1, "Should group sites across scheme, port and origin attributes"); + let columns = siteItems[0].querySelectorAll(".item-box > label"); + let expected = "account.xyz.com"; - let host = siteItems[0].getAttribute("host"); - is(host, expected, "Should group and list sites by host"); + is(columns[0].value, expected, "Should group and list sites by host"); let prefStrBundle = frameDoc.getElementById("bundlePreferences"); + expected = prefStrBundle.getString("persistent"); + is(columns[1].value, expected, "Should mark persisted status across scheme, port and origin attributes"); + + is(columns[2].value, "5", "Should group cookies across scheme, port and origin attributes"); + expected = prefStrBundle.getFormattedString("siteUsage", DownloadUtils.convertByteUnits(quotaUsage * mockSiteDataManager.fakeSites.length)); - let usage = siteItems[0].getAttribute("usage"); - is(usage, expected, "Should sum up usages across scheme, port and origin attributes"); - - expected = prefStrBundle.getString("persistent"); - let status = siteItems[0].getAttribute("status"); - is(status, expected, "Should mark persisted status across scheme, port and origin attributes"); + is(columns[3].value, expected, "Should sum up usages across scheme, port and origin attributes"); mockSiteDataManager.unregister(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test sorting add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", + cookies: 6, persisted: true }, { usage: 1024 * 2, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://books.foo.com"), + origin: "https://books.foo.com", + cookies: 0, persisted: false }, { usage: 1024 * 3, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", + cookies: 3, persisted: true }, - ]; + ]); let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); let dialog = content.gSubDialog._topDialog; let dialogFrame = dialog._frame; let frameDoc = dialogFrame.contentDocument; let hostCol = frameDoc.getElementById("hostCol"); let usageCol = frameDoc.getElementById("usageCol"); let statusCol = frameDoc.getElementById("statusCol"); + let cookiesCol = frameDoc.getElementById("cookiesCol"); let sitesList = frameDoc.getElementById("sitesList"); // Test default sorting assertSortByUsage("descending"); // Test sorting on the usage column usageCol.click(); assertSortByUsage("ascending"); usageCol.click(); assertSortByUsage("descending"); // Test sorting on the host column hostCol.click(); - assertSortByHost("ascending"); + assertSortByBaseDomain("ascending"); hostCol.click(); - assertSortByHost("descending"); + assertSortByBaseDomain("descending") // Test sorting on the permission status column + cookiesCol.click(); + assertSortByCookies("ascending"); + cookiesCol.click(); + assertSortByCookies("descending"); + + // Test sorting on the cookies column statusCol.click(); assertSortByStatus("ascending"); statusCol.click(); assertSortByStatus("descending"); mockSiteDataManager.unregister(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); - function assertSortByHost(order) { + function assertSortByBaseDomain(order) { let siteItems = sitesList.getElementsByTagName("richlistitem"); for (let i = 0; i < siteItems.length - 1; ++i) { let aHost = siteItems[i].getAttribute("host"); let bHost = siteItems[i + 1].getAttribute("host"); - let result = aHost.localeCompare(bHost); + let a = findSiteByHost(aHost); + let b = findSiteByHost(bHost); + let result = a.baseDomain.localeCompare(b.baseDomain); if (order == "ascending") { Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host"); } else { Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host"); } } } @@ -214,12 +223,28 @@ add_task(async function() { if (order == "ascending") { Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage"); } else { Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage"); } } } + function assertSortByCookies(order) { + let siteItems = sitesList.getElementsByTagName("richlistitem"); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aHost = siteItems[i].getAttribute("host"); + let bHost = siteItems[i + 1].getAttribute("host"); + let a = findSiteByHost(aHost); + let b = findSiteByHost(bHost); + let result = a.cookies.length - b.cookies.length; + if (order == "ascending") { + Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by number of cookies"); + } else { + Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by number of cookies"); + } + } + } + function findSiteByHost(host) { return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host); } }); diff --git a/browser/components/preferences/in-content-new/tests/head.js b/browser/components/preferences/in-content-new/tests/head.js --- a/browser/components/preferences/in-content-new/tests/head.js +++ b/browser/components/preferences/in-content-new/tests/head.js @@ -262,26 +262,48 @@ const mockSiteDataManager = { _removeQuotaUsage(site) { var target = site.principals[0].URI.host; this.fakeSites = this.fakeSites.filter(fakeSite => { return fakeSite.principal.URI.host != target; }); }, - register(SiteDataManager) { + register(SiteDataManager, fakeSites) { this._SiteDataManager = SiteDataManager; this._originalQMS = this._SiteDataManager._qms; this._SiteDataManager._qms = this; this._originalRemoveQuotaUsage = this._SiteDataManager._removeQuotaUsage; this._SiteDataManager._removeQuotaUsage = this._removeQuotaUsage.bind(this); - this.fakeSites = null; + // Add some fake data. + this.fakeSites = fakeSites; + for (let site of fakeSites) { + if (!site.principal) { + site.principal = Services.scriptSecurityManager + .createCodebasePrincipalFromOrigin(site.origin); + } + + let uri = site.principal.URI; + try { + site.baseDomain = Services.eTLD.getBaseDomainFromHost(uri.host); + } catch (e) { + site.baseDomain = uri.host; + } + + // Add some cookies if needed. + for (let i = 0; i < (site.cookies || 0); i++) { + Services.cookies.add(uri.host, uri.path, Cu.now(), i, + false, false, false, Date.now() + 1000 * 60 * 60); + } + } }, unregister() { + this.fakeSites = null; + this._SiteDataManager.removeAll(); this._SiteDataManager._qms = this._originalQMS; this._SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage; } }; function getQuotaUsage(origin) { return new Promise(resolve => { let uri = NetUtil.newURI(origin); diff --git a/browser/components/preferences/in-content/tests/browser_siteData.js b/browser/components/preferences/in-content/tests/browser_siteData.js --- a/browser/components/preferences/in-content/tests/browser_siteData.js +++ b/browser/components/preferences/in-content/tests/browser_siteData.js @@ -155,8 +155,99 @@ add_task(async function() { ok(false, `Should have one site of ${host}`); } }); await acceptRemovePromise; await updatePromise; await promiseServiceWorkersCleared(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); + +// Test showing and removing sites with cookies. +add_task(async function() { + SiteDataManager.removeAll(); + + // Add some test cookies. + let uri = Services.io.newURI("https://example.com"); + let uri2 = Services.io.newURI("https://example.org"); + Services.cookies.add(uri.host, uri.path, "test1", "1", + false, false, false, Date.now() + 1000 * 60 * 60); + Services.cookies.add(uri.host, uri.path, "test2", "2", + false, false, false, Date.now() + 1000 * 60 * 60); + Services.cookies.add(uri2.host, uri2.path, "test1", "1", + false, false, false, Date.now() + 1000 * 60 * 60); + + // Ensure that private browsing cookies are ignored. + Services.cookies.add(uri.host, uri.path, "test3", "3", + false, false, false, Date.now() + 1000 * 60 * 60, { privateBrowsingId: 1 }); + + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + + // Open the site data manager and remove one site. + await openSiteDataSettingsDialog(); + let removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL); + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + let frameDoc = content.gSubDialog._topDialog._frame.contentDocument; + + let siteItems = frameDoc.getElementsByTagName("richlistitem"); + is(siteItems.length, 2, "Should list two sites with cookies"); + let sitesList = frameDoc.getElementById("sitesList"); + let site1 = sitesList.querySelector(`richlistitem[host="example.com"]`); + let site2 = sitesList.querySelector(`richlistitem[host="example.org"]`); + + let columns = site1.querySelectorAll(".item-box > label"); + is(columns[0].value, "example.com", "Should show the correct host."); + is(columns[2].value, "2", "Should show the correct number of cookies."); + is(columns[3].value, "", "Should show no site data."); + + columns = site2.querySelectorAll(".item-box > label"); + is(columns[0].value, "example.org", "Should show the correct host."); + is(columns[2].value, "1", "Should show the correct number of cookies."); + is(columns[3].value, "", "Should show no site data."); + + let removeBtn = frameDoc.getElementById("removeSelected"); + let saveBtn = frameDoc.getElementById("save"); + site2.click(); + removeBtn.doCommand(); + saveBtn.doCommand(); + }); + await removeDialogOpenPromise; + + await TestUtils.waitForCondition(() => Services.cookies.countCookiesFromHost(uri2.host) == 0, "Cookies from the first host should be cleared"); + is(Services.cookies.countCookiesFromHost(uri.host), 2, "Cookies from the second host should not be cleared"); + + // Open the site data manager and remove another site. + await openSiteDataSettingsDialog(); + let acceptRemovePromise = promiseAlertDialogOpen("accept"); + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + let frameDoc = content.gSubDialog._topDialog._frame.contentDocument; + + let siteItems = frameDoc.getElementsByTagName("richlistitem"); + is(siteItems.length, 1, "Should list one site with cookies"); + let sitesList = frameDoc.getElementById("sitesList"); + let site1 = sitesList.querySelector(`richlistitem[host="example.com"]`); + + let columns = site1.querySelectorAll(".item-box > label"); + is(columns[0].value, "example.com", "Should show the correct host."); + is(columns[2].value, "2", "Should show the correct number of cookies."); + is(columns[3].value, "", "Should show no site data."); + + let removeBtn = frameDoc.getElementById("removeSelected"); + let saveBtn = frameDoc.getElementById("save"); + site1.click(); + removeBtn.doCommand(); + saveBtn.doCommand(); + }); + await acceptRemovePromise; + + await TestUtils.waitForCondition(() => Services.cookies.countCookiesFromHost(uri.host) == 0, "Cookies from the second host should be cleared"); + + await openSiteDataSettingsDialog(); + + ContentTask.spawn(gBrowser.selectedBrowser, null, function() { + let frameDoc = content.gSubDialog._topDialog._frame.contentDocument; + + let siteItems = frameDoc.getElementsByTagName("richlistitem"); + is(siteItems.length, 0, "Should list no sites with cookies"); + }); + + await BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); diff --git a/browser/components/preferences/in-content/tests/browser_siteData2.js b/browser/components/preferences/in-content/tests/browser_siteData2.js --- a/browser/components/preferences/in-content/tests/browser_siteData2.js +++ b/browser/components/preferences/in-content/tests/browser_siteData2.js @@ -10,43 +10,38 @@ function assertAllSitesNotListed(win) { is(sites.length, 0, "Should not list all sites"); is(removeBtn.disabled, true, "Should disable the removeSelected button"); is(removeAllBtn.disabled, true, "Should disable the removeAllBtn button"); } // Test selecting and removing all sites one by one add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register([ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true }); await updatePromise; await openSettingsDialog(); let win = gBrowser.selectedBrowser.contentWindow; @@ -70,20 +65,22 @@ add_task(async function() { await openSettingsDialog(); assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button but cancelling save let cancelPromise = promiseAlertDialogOpen("cancel"); settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; saveBtn = frameDoc.getElementById("save"); + cancelBtn = frameDoc.getElementById("cancel"); removeAllSitesOneByOne(); assertAllSitesNotListed(win); saveBtn.doCommand(); await cancelPromise; + cancelBtn.doCommand(); await settingsDialogClosePromise; await openSettingsDialog(); assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button and accepting save let acceptPromise = promiseAlertDialogOpen("accept"); settingsDialogClosePromise = promiseSettingsDialogClose(); updatePromise = promiseSitesUpdated(); @@ -111,61 +108,53 @@ add_task(async function() { removeBtn.doCommand(); } } }); // Test selecting and removing partial sites add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register([ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://s3-us-west-2.amazonaws.com"), + origin: "https://s3-us-west-2.amazonaws.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://127.0.0.1"), + origin: "https://127.0.0.1", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://[0:0:0:0:0:0:0:1]"), + origin: "https://[0:0:0:0:0:0:0:1]", persisted: true }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true }); await updatePromise; await openSettingsDialog(); let win = gBrowser.selectedBrowser.contentWindow; @@ -190,20 +179,22 @@ add_task(async function() { await openSettingsDialog(); assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button but canceling save removeDialogOpenPromise = promiseWindowDialogOpen("cancel", REMOVE_DIALOG_URL); settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; saveBtn = frameDoc.getElementById("save"); + cancelBtn = frameDoc.getElementById("cancel"); removeSelectedSite(fakeHosts.slice(0, 2)); assertSitesListed(doc, fakeHosts.slice(2)); saveBtn.doCommand(); await removeDialogOpenPromise; + cancelBtn.doCommand(); await settingsDialogClosePromise; await openSettingsDialog(); assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button and accepting save removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL); settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; @@ -235,43 +226,38 @@ add_task(async function() { } }); } }); // Test searching and then removing only visible sites add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register([ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true }); await updatePromise; await openSettingsDialog(); // Search "foo" to only list foo.com sites @@ -299,31 +285,28 @@ add_task(async function() { mockSiteDataManager.unregister(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test dynamically clearing all site data add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register([ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); // Test the initial state let updatePromise = promiseSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true }); await updatePromise; await openSettingsDialog(); let doc = gBrowser.selectedBrowser.contentDocument; diff --git a/browser/components/preferences/in-content/tests/browser_siteData3.js b/browser/components/preferences/in-content/tests/browser_siteData3.js --- a/browser/components/preferences/in-content/tests/browser_siteData3.js +++ b/browser/components/preferences/in-content/tests/browser_siteData3.js @@ -1,40 +1,35 @@ "use strict"; // Test search on the host column add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register([ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, - ]; + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true }); await updatePromise; await openSettingsDialog(); let win = gBrowser.selectedBrowser.contentWindow; @@ -56,124 +51,133 @@ add_task(async function() { mockSiteDataManager.unregister(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test not displaying sites which store 0 byte and don't have persistent storage. add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register([ { usage: 0, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", persisted: true }, { usage: 0, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"), + origin: "https://shopping.xyz.com", persisted: false }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", persisted: true }, { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), + origin: "http://email.bar.com", persisted: false }, - ]; + { + usage: 0, + origin: "http://cookies.bar.com", + cookies: 5, + persisted: false + }, + ]); let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSitesUpdated(); let doc = gBrowser.selectedBrowser.contentDocument; await openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true }); await updatePromise; await openSettingsDialog(); assertSitesListed(doc, fakeHosts.filter(host => host != "shopping.xyz.com")); mockSiteDataManager.unregister(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test sorting add_task(async function() { await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]}); - mockSiteDataManager.register(SiteDataManager); - mockSiteDataManager.fakeSites = [ + mockSiteDataManager.register([ { usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://account.xyz.com"), + origin: "https://account.xyz.com", + cookies: 6, persisted: true }, { usage: 1024 * 2, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("https://books.foo.com"), + origin: "https://books.foo.com", + cookies: 0, persisted: false }, { usage: 1024 * 3, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + origin: "http://cinema.bar.com", + cookies: 3, persisted: true }, - ]; + ]); let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); let dialog = content.gSubDialog._topDialog; let dialogFrame = dialog._frame; let frameDoc = dialogFrame.contentDocument; let hostCol = frameDoc.getElementById("hostCol"); let usageCol = frameDoc.getElementById("usageCol"); let statusCol = frameDoc.getElementById("statusCol"); + let cookiesCol = frameDoc.getElementById("cookiesCol"); let sitesList = frameDoc.getElementById("sitesList"); // Test default sorting assertSortByUsage("descending"); // Test sorting on the usage column usageCol.click(); assertSortByUsage("ascending"); usageCol.click(); assertSortByUsage("descending"); // Test sorting on the host column hostCol.click(); - assertSortByHost("ascending"); + assertSortByBaseDomain("ascending"); hostCol.click(); - assertSortByHost("descending"); + assertSortByBaseDomain("descending"); // Test sorting on the permission status column + cookiesCol.click(); + assertSortByCookies("ascending"); + cookiesCol.click(); + assertSortByCookies("descending"); + + // Test sorting on the cookies column statusCol.click(); assertSortByStatus("ascending"); statusCol.click(); assertSortByStatus("descending"); mockSiteDataManager.unregister(); await BrowserTestUtils.removeTab(gBrowser.selectedTab); - function assertSortByHost(order) { + function assertSortByBaseDomain(order) { let siteItems = sitesList.getElementsByTagName("richlistitem"); for (let i = 0; i < siteItems.length - 1; ++i) { let aHost = siteItems[i].getAttribute("host"); let bHost = siteItems[i + 1].getAttribute("host"); - let result = aHost.localeCompare(bHost); + let a = findSiteByHost(aHost); + let b = findSiteByHost(bHost); + let result = a.baseDomain.localeCompare(b.baseDomain); if (order == "ascending") { Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host"); } else { Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host"); } } } @@ -209,12 +213,28 @@ add_task(async function() { if (order == "ascending") { Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage"); } else { Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage"); } } } + function assertSortByCookies(order) { + let siteItems = sitesList.getElementsByTagName("richlistitem"); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aHost = siteItems[i].getAttribute("host"); + let bHost = siteItems[i + 1].getAttribute("host"); + let a = findSiteByHost(aHost); + let b = findSiteByHost(bHost); + let result = a.cookies.length - b.cookies.length; + if (order == "ascending") { + Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by number of cookies"); + } else { + Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by number of cookies"); + } + } + } + function findSiteByHost(host) { return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host); } }); diff --git a/browser/components/preferences/in-content/tests/head.js b/browser/components/preferences/in-content/tests/head.js --- a/browser/components/preferences/in-content/tests/head.js +++ b/browser/components/preferences/in-content/tests/head.js @@ -34,25 +34,47 @@ const mockSiteDataManager = { _removeQuotaUsage(site) { var target = site.principals[0].URI.host; this.fakeSites = this.fakeSites.filter(fakeSite => { return fakeSite.principal.URI.host != target; }); }, - register() { + register(fakeSites) { this._originalQMS = SiteDataManager._qms; SiteDataManager._qms = this; this._originalRemoveQuotaUsage = SiteDataManager._removeQuotaUsage; SiteDataManager._removeQuotaUsage = this._removeQuotaUsage.bind(this); - this.fakeSites = null; + // Add some fake data. + this.fakeSites = fakeSites; + for (let site of fakeSites) { + if (!site.principal) { + site.principal = Services.scriptSecurityManager + .createCodebasePrincipalFromOrigin(site.origin); + } + + let uri = site.principal.URI; + try { + site.baseDomain = Services.eTLD.getBaseDomainFromHost(uri.host); + } catch (e) { + site.baseDomain = uri.host; + } + + // Add some cookies if needed. + for (let i = 0; i < (site.cookies || 0); i++) { + Services.cookies.add(uri.host, uri.path, Cu.now(), i, + false, false, false, Date.now() + 1000 * 60 * 60); + } + } }, unregister() { + this.fakeSites = null; + SiteDataManager.removeAll(); SiteDataManager._qms = this._originalQMS; SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage; } }; function is_hidden(aElement) { var style = aElement.ownerGlobal.getComputedStyle(aElement); if (style.display == "none")