diff --git a/browser/modules/test/browser/browser.ini b/browser/modules/test/browser/browser.ini index 89f10318d9b0..a1221adf028a 100644 --- a/browser/modules/test/browser/browser.ini +++ b/browser/modules/test/browser/browser.ini @@ -34,6 +34,7 @@ skip-if = os != "win" run-if = crashreporter [browser_urlBar_zoom.js] [browser_UsageTelemetry.js] +[browser_UsageTelemetry_domains.js] [browser_UsageTelemetry_private_and_restore.js] [browser_UsageTelemetry_urlbar.js] skip-if = (os == 'linux' && bits == 32 && debug) # bug 1356758 diff --git a/browser/modules/test/browser/browser_UsageTelemetry.js b/browser/modules/test/browser/browser_UsageTelemetry.js index f1b63d8acd7d..3bff25df214d 100644 --- a/browser/modules/test/browser/browser_UsageTelemetry.js +++ b/browser/modules/test/browser/browser_UsageTelemetry.js @@ -16,53 +16,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "MINIMUM_TAB_COUNT_INTERVAL_MS", // Reset internal URI counter in case URIs were opened by other tests. Services.obs.notifyObservers(null, TELEMETRY_SUBSESSION_TOPIC); -/** - * Waits for the web progress listener associated with this tab to fire an - * onLocationChange for a non-error page. - * - * @param {xul:browser} browser - * A xul:browser. - * - * @return {Promise} - * @resolves When navigating to a non-error page. - */ -function browserLocationChanged(browser) { - return new Promise(resolve => { - let wpl = { - onStateChange() {}, - onSecurityChange() {}, - onStatusChange() {}, - onLocationChange(aWebProgress, aRequest, aURI, aFlags) { - if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) { - browser.webProgress.removeProgressListener(filter); - filter.removeProgressListener(wpl); - resolve(); - } - }, - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIWebProgressListener, - Ci.nsIWebProgressListener2, - ]), - }; - const filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"] - .createInstance(Ci.nsIWebProgress); - filter.addProgressListener(wpl, Ci.nsIWebProgress.NOTIFY_ALL); - browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL); - }); -} - -/** - * An helper that checks the value of a scalar if it's expected to be > 0, - * otherwise makes sure that the scalar it's not reported. - */ -let checkScalar = (scalars, scalarName, value, msg) => { - if (value > 0) { - is(scalars[scalarName], value, msg); - return; - } - ok(!(scalarName in scalars), scalarName + " must not be reported."); -}; - /** * Get a snapshot of the scalars and check them against the provided values. */ @@ -183,94 +136,6 @@ add_task(async function test_subsessionSplit() { await BrowserTestUtils.closeWindow(win); }); -add_task(async function test_URIAndDomainCounts() { - // Let's reset the counts. - Services.telemetry.clearScalars(); - - let checkCounts = (countsObject) => { - // Get a snapshot of the scalars and then clear them. - const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN); - checkScalar(scalars, TOTAL_URI_COUNT, countsObject.totalURIs, - "The URI scalar must contain the expected value."); - checkScalar(scalars, UNIQUE_DOMAINS_COUNT, countsObject.domainCount, - "The unique domains scalar must contain the expected value."); - checkScalar(scalars, UNFILTERED_URI_COUNT, countsObject.totalUnfilteredURIs, - "The unfiltered URI scalar must contain the expected value."); - }; - - // Check that about:blank doesn't get counted in the URI total. - let firstTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"); - checkCounts({totalURIs: 0, domainCount: 0, totalUnfilteredURIs: 0}); - - // Open a different page and check the counts. - await BrowserTestUtils.loadURI(firstTab.linkedBrowser, "http://example.com/"); - await BrowserTestUtils.browserLoaded(firstTab.linkedBrowser); - checkCounts({totalURIs: 1, domainCount: 1, totalUnfilteredURIs: 1}); - - // Activating a different tab must not increase the URI count. - let secondTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"); - await BrowserTestUtils.switchTab(gBrowser, firstTab); - checkCounts({totalURIs: 1, domainCount: 1, totalUnfilteredURIs: 1}); - await BrowserTestUtils.removeTab(secondTab); - - // Open a new window and set the tab to a new address. - let newWin = await BrowserTestUtils.openNewBrowserWindow(); - await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://example.com/"); - await BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser); - checkCounts({totalURIs: 2, domainCount: 1, totalUnfilteredURIs: 2}); - - // We should not count AJAX requests. - const XHR_URL = "http://example.com/r"; - await ContentTask.spawn(newWin.gBrowser.selectedBrowser, XHR_URL, function(url) { - return new Promise(resolve => { - var xhr = new content.window.XMLHttpRequest(); - xhr.open("GET", url); - xhr.onload = () => resolve(); - xhr.send(); - }); - }); - checkCounts({totalURIs: 2, domainCount: 1, totalUnfilteredURIs: 2}); - - // Check that we're counting page fragments. - let loadingStopped = browserLocationChanged(newWin.gBrowser.selectedBrowser); - await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://example.com/#2"); - await loadingStopped; - checkCounts({totalURIs: 3, domainCount: 1, totalUnfilteredURIs: 3}); - - // Check that a different URI from the example.com domain doesn't increment the unique count. - await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://test1.example.com/"); - await BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser); - checkCounts({totalURIs: 4, domainCount: 1, totalUnfilteredURIs: 4}); - - // Make sure that the unique domains counter is incrementing for a different domain. - await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "https://example.org/"); - await BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser); - checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 5}); - - // Check that we only account for top level loads (e.g. we don't count URIs from - // embedded iframes). - await ContentTask.spawn(newWin.gBrowser.selectedBrowser, null, async function() { - let doc = content.document; - let iframe = doc.createElement("iframe"); - let promiseIframeLoaded = ContentTaskUtils.waitForEvent(iframe, "load", false); - iframe.src = "https://example.org/test"; - doc.body.insertBefore(iframe, doc.body.firstChild); - await promiseIframeLoaded; - }); - checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 5}); - - // Check that uncommon protocols get counted in the unfiltered URI probe. - const TEST_PAGE = - "data:text/html,Click meThe paragraph."; - await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, TEST_PAGE); - await BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser); - checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 6}); - - // Clean up. - await BrowserTestUtils.removeTab(firstTab); - await BrowserTestUtils.closeWindow(newWin); -}); - function checkTabCountHistogram(result, expected, message) { let expectedPadded = result.counts.map((val, idx) => idx < expected.length ? expected[idx] : 0); Assert.deepEqual(result.counts, expectedPadded, message); diff --git a/browser/modules/test/browser/browser_UsageTelemetry_domains.js b/browser/modules/test/browser/browser_UsageTelemetry_domains.js new file mode 100644 index 000000000000..a8d8cb2640b5 --- /dev/null +++ b/browser/modules/test/browser/browser_UsageTelemetry_domains.js @@ -0,0 +1,132 @@ +"use strict"; + +const TOTAL_URI_COUNT = "browser.engagement.total_uri_count"; +const UNIQUE_DOMAINS_COUNT = "browser.engagement.unique_domains_count"; +const UNFILTERED_URI_COUNT = "browser.engagement.unfiltered_uri_count"; +const TELEMETRY_SUBSESSION_TOPIC = "internal-telemetry-after-subsession-split"; + +// Reset internal URI counter in case URIs were opened by other tests. +Services.obs.notifyObservers(null, TELEMETRY_SUBSESSION_TOPIC); + +/** + * Waits for the web progress listener associated with this tab to fire an + * onLocationChange for a non-error page. + * + * @param {xul:browser} browser + * A xul:browser. + * + * @return {Promise} + * @resolves When navigating to a non-error page. + */ +function browserLocationChanged(browser) { + return new Promise(resolve => { + let wpl = { + onStateChange() {}, + onSecurityChange() {}, + onStatusChange() {}, + onLocationChange(aWebProgress, aRequest, aURI, aFlags) { + if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) { + browser.webProgress.removeProgressListener(filter); + filter.removeProgressListener(wpl); + resolve(); + } + }, + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIWebProgressListener, + Ci.nsIWebProgressListener2, + ]), + }; + const filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"] + .createInstance(Ci.nsIWebProgress); + filter.addProgressListener(wpl, Ci.nsIWebProgress.NOTIFY_ALL); + browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL); + }); +} + +add_task(async function test_URIAndDomainCounts() { + // Let's reset the counts. + Services.telemetry.clearScalars(); + + let checkCounts = (countsObject) => { + // Get a snapshot of the scalars and then clear them. + const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN); + checkScalar(scalars, TOTAL_URI_COUNT, countsObject.totalURIs, + "The URI scalar must contain the expected value."); + checkScalar(scalars, UNIQUE_DOMAINS_COUNT, countsObject.domainCount, + "The unique domains scalar must contain the expected value."); + checkScalar(scalars, UNFILTERED_URI_COUNT, countsObject.totalUnfilteredURIs, + "The unfiltered URI scalar must contain the expected value."); + }; + + // Check that about:blank doesn't get counted in the URI total. + let firstTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"); + checkCounts({totalURIs: 0, domainCount: 0, totalUnfilteredURIs: 0}); + + // Open a different page and check the counts. + await BrowserTestUtils.loadURI(firstTab.linkedBrowser, "http://example.com/"); + await BrowserTestUtils.browserLoaded(firstTab.linkedBrowser); + checkCounts({totalURIs: 1, domainCount: 1, totalUnfilteredURIs: 1}); + + // Activating a different tab must not increase the URI count. + let secondTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"); + await BrowserTestUtils.switchTab(gBrowser, firstTab); + checkCounts({totalURIs: 1, domainCount: 1, totalUnfilteredURIs: 1}); + await BrowserTestUtils.removeTab(secondTab); + + // Open a new window and set the tab to a new address. + let newWin = await BrowserTestUtils.openNewBrowserWindow(); + await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://example.com/"); + await BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser); + checkCounts({totalURIs: 2, domainCount: 1, totalUnfilteredURIs: 2}); + + // We should not count AJAX requests. + const XHR_URL = "http://example.com/r"; + await ContentTask.spawn(newWin.gBrowser.selectedBrowser, XHR_URL, function(url) { + return new Promise(resolve => { + var xhr = new content.window.XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = () => resolve(); + xhr.send(); + }); + }); + checkCounts({totalURIs: 2, domainCount: 1, totalUnfilteredURIs: 2}); + + // Check that we're counting page fragments. + let loadingStopped = browserLocationChanged(newWin.gBrowser.selectedBrowser); + await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://example.com/#2"); + await loadingStopped; + checkCounts({totalURIs: 3, domainCount: 1, totalUnfilteredURIs: 3}); + + // Check that a different URI from the example.com domain doesn't increment the unique count. + await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "http://test1.example.com/"); + await BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser); + checkCounts({totalURIs: 4, domainCount: 1, totalUnfilteredURIs: 4}); + + // Make sure that the unique domains counter is incrementing for a different domain. + await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, "https://example.org/"); + await BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser); + checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 5}); + + // Check that we only account for top level loads (e.g. we don't count URIs from + // embedded iframes). + await ContentTask.spawn(newWin.gBrowser.selectedBrowser, null, async function() { + let doc = content.document; + let iframe = doc.createElement("iframe"); + let promiseIframeLoaded = ContentTaskUtils.waitForEvent(iframe, "load", false); + iframe.src = "https://example.org/test"; + doc.body.insertBefore(iframe, doc.body.firstChild); + await promiseIframeLoaded; + }); + checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 5}); + + // Check that uncommon protocols get counted in the unfiltered URI probe. + const TEST_PAGE = + "data:text/html,Click meThe paragraph."; + await BrowserTestUtils.loadURI(newWin.gBrowser.selectedBrowser, TEST_PAGE); + await BrowserTestUtils.browserLoaded(newWin.gBrowser.selectedBrowser); + checkCounts({totalURIs: 5, domainCount: 2, totalUnfilteredURIs: 6}); + + // Clean up. + await BrowserTestUtils.removeTab(firstTab); + await BrowserTestUtils.closeWindow(newWin); +}); diff --git a/browser/modules/test/browser/head.js b/browser/modules/test/browser/head.js index 09baefb66693..06786206509a 100644 --- a/browser/modules/test/browser/head.js +++ b/browser/modules/test/browser/head.js @@ -57,6 +57,27 @@ function checkKeyedScalar(scalars, scalarName, key, expectedValue) { scalarName + "['" + key + "'] must contain the expected value"); } +/** + * An helper that checks the value of a scalar if it's expected to be > 0, + * otherwise makes sure that the scalar it's not reported. + * + * @param {Object} scalars + * The snapshot of the scalars. + * @param {String} scalarName + * The name of the scalar to check. + * @param {Number} value + * The expected value for the provided scalar. + * @param {String} msg + * The message to print when checking the value. + */ +let checkScalar = (scalars, scalarName, value, msg) => { + if (value > 0) { + is(scalars[scalarName], value, msg); + return; + } + ok(!(scalarName in scalars), scalarName + " must not be reported."); +}; + /** * An utility function to write some text in the search input box * in a content page.