From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser_search_telemetry_sources_ads.js | 841 +++++++++++++++++++++ 1 file changed, 841 insertions(+) create mode 100644 browser/components/search/test/browser/browser_search_telemetry_sources_ads.js (limited to 'browser/components/search/test/browser/browser_search_telemetry_sources_ads.js') diff --git a/browser/components/search/test/browser/browser_search_telemetry_sources_ads.js b/browser/components/search/test/browser/browser_search_telemetry_sources_ads.js new file mode 100644 index 0000000000..880497f993 --- /dev/null +++ b/browser/components/search/test/browser/browser_search_telemetry_sources_ads.js @@ -0,0 +1,841 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * Main tests for SearchSERPTelemetry - general engine visiting and link clicking. + */ + +"use strict"; + +const { SearchSERPTelemetry, SearchSERPTelemetryUtils } = + ChromeUtils.importESModule("resource:///modules/SearchSERPTelemetry.sys.mjs"); + +// Note: example.org is used for the SERP page, and example.com is used to serve +// the ads. This is done to simulate different domains like the real servers. +const TEST_PROVIDER_INFO = [ + { + telemetryId: "example", + searchPageRegexp: + /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/searchTelemetry(?:Ad)?.html/, + queryParamName: "s", + codeParamName: "abc", + taggedCodes: ["ff"], + followOnParamNames: ["a"], + extraAdServersRegexps: [/^https:\/\/example\.com\/ad2?/], + components: [ + { + type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + default: true, + }, + ], + }, + { + telemetryId: "example-data-attributes", + searchPageRegexp: + /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/searchTelemetryAd_dataAttributes(?:_none|_href)?.html/, + queryParamName: "s", + codeParamName: "abc", + taggedCodes: ["ff"], + adServerAttributes: ["xyz"], + extraAdServersRegexps: [/^https:\/\/example\.com\/ad/], + components: [ + { + type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + default: true, + }, + ], + }, + { + telemetryId: "slow-page-load", + searchPageRegexp: + /^https:\/\/example.org\/browser\/browser\/components\/search\/test\/browser\/slow_loading_page_with_ads(_on_load_event)?.html/, + queryParamName: "s", + codeParamName: "abc", + taggedCodes: ["ff"], + followOnParamNames: ["a"], + extraAdServersRegexps: [/^https:\/\/example\.com\/ad2?/], + components: [ + { + type: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + default: true, + }, + ], + }, +]; + +function getPageUrl(useAdPage = false) { + let page = useAdPage ? "searchTelemetryAd.html" : "searchTelemetry.html"; + return `https://example.org/browser/browser/components/search/test/browser/${page}`; +} + +function getSERPUrl(page, organic = false) { + return `${page}?s=test${organic ? "" : "&abc=ff"}`; +} + +function getSERPFollowOnUrl(page) { + return page + "?s=test&abc=ff&a=foo"; +} + +// sharedData messages are only passed to the child on idle. Therefore +// we wait for a few idles to try and ensure the messages have been able +// to be passed across and handled. +async function waitForIdle() { + for (let i = 0; i < 10; i++) { + await new Promise(resolve => Services.tm.idleDispatchToMainThread(resolve)); + } +} + +add_setup(async function () { + SearchSERPTelemetry.overrideSearchTelemetryForTests(TEST_PROVIDER_INFO); + await waitForIdle(); + // Enable local telemetry recording for the duration of the tests. + let oldCanRecord = Services.telemetry.canRecordExtended; + Services.telemetry.canRecordExtended = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.search.log", true], + ["browser.search.serpEventTelemetry.enabled", true], + ], + }); + + registerCleanupFunction(async () => { + SearchSERPTelemetry.overrideSearchTelemetryForTests(); + Services.telemetry.canRecordExtended = oldCanRecord; + resetTelemetry(); + }); +}); + +add_task(async function test_simple_search_page_visit() { + resetTelemetry(); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: getSERPUrl(getPageUrl()), + }, + async () => { + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "example:tagged:ff": 1 }, + } + ); + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); +}); + +add_task(async function test_simple_search_page_visit_telemetry() { + resetTelemetry(); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + /* URL must not be in the cache */ + url: getSERPUrl(getPageUrl()) + `&random=${Math.random()}`, + }, + async () => { + let scalars = {}; + const key = "browser.search.data_transferred"; + + await TestUtils.waitForCondition(() => { + scalars = + Services.telemetry.getSnapshotForKeyedScalars("main", false).parent || + {}; + return key in scalars; + }, "should have the expected keyed scalars"); + + const scalar = scalars[key]; + Assert.ok("example" in scalar, "correct telemetry category"); + Assert.notEqual(scalars[key].example, 0, "bandwidth logged"); + } + ); + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); +}); + +add_task(async function test_follow_on_visit() { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: getSERPFollowOnUrl(getPageUrl()), + }, + async () => { + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example:tagged:ff": 1, + "example:tagged-follow-on:ff": 1, + }, + } + ); + } + ); + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); +}); + +add_task(async function test_track_ad() { + resetTelemetry(); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(getPageUrl(true)) + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "example:tagged:ff": 1 }, + "browser.search.withads.unknown": { "example:tagged": 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_track_ad_on_data_attributes() { + resetTelemetry(); + + let url = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.org" + ) + "searchTelemetryAd_dataAttributes.html"; + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(url) + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example-data-attributes:tagged:ff": 1, + }, + "browser.search.withads.unknown": { + "example-data-attributes:tagged": 1, + }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example-data-attributes", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_track_ad_on_data_attributes_and_hrefs() { + resetTelemetry(); + + let url = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.org" + ) + "searchTelemetryAd_dataAttributes_href.html"; + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(url) + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example-data-attributes:tagged:ff": 1, + }, + "browser.search.withads.unknown": { + "example-data-attributes:tagged": 1, + }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example-data-attributes", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_track_no_ad_on_data_attributes_and_hrefs() { + resetTelemetry(); + + let url = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.org" + ) + "searchTelemetryAd_dataAttributes_none.html"; + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(url) + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { + "example-data-attributes:tagged:ff": 1, + }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example-data-attributes", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_track_ad_on_DOMContentLoaded() { + resetTelemetry(); + + let url = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.org" + ) + "slow_loading_page_with_ads.html"; + + let observeAdPreviouslyRecorded = TestUtils.consoleMessageObserved(msg => { + return ( + typeof msg.wrappedJSObject.arguments?.[0] == "string" && + msg.wrappedJSObject.arguments[0].includes( + "Ad was previously reported for browser with URI" + ) + ); + }); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(url) + ); + + // Observe ad was counted on DOMContentLoaded. + // We do not count the ad again on load. + await observeAdPreviouslyRecorded; + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "slow-page-load:tagged:ff": 1 }, + "browser.search.withads.unknown": { "slow-page-load:tagged": 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "slow-page-load", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_track_ad_on_load_event() { + resetTelemetry(); + + let url = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.org" + ) + "slow_loading_page_with_ads_on_load_event.html"; + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(url) + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "slow-page-load:tagged:ff": 1 }, + "browser.search.withads.unknown": { "slow-page-load:tagged": 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "slow-page-load", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_track_ad_organic() { + resetTelemetry(); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(getPageUrl(true), true) + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "example:organic:none": 1 }, + "browser.search.withads.unknown": { "example:organic": 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "false", + partner_code: "", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_track_ad_new_window() { + resetTelemetry(); + + let win = await BrowserTestUtils.openNewBrowserWindow(); + + let url = getSERPUrl(getPageUrl(true)); + BrowserTestUtils.loadURIString(win.gBrowser.selectedBrowser, url); + await BrowserTestUtils.browserLoaded( + win.gBrowser.selectedBrowser, + false, + url + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "example:tagged:ff": 1 }, + "browser.search.withads.unknown": { "example:tagged": 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_track_ad_pages_without_ads() { + // Note: the above tests have already checked a page with no ad-urls. + resetTelemetry(); + + let tabs = []; + + tabs.push( + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(getPageUrl(false)) + ) + ); + tabs.push( + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(getPageUrl(true)) + ) + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "example:tagged:ff": 2 }, + "browser.search.withads.unknown": { "example:tagged": 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + + for (let tab of tabs) { + BrowserTestUtils.removeTab(tab); + } +}); + +async function track_ad_click(testOrganic) { + // Note: the above tests have already checked a page with no ad-urls. + resetTelemetry(); + + let expectedScalarKey = `example:${testOrganic ? "organic" : "tagged"}`; + let expectedContentScalarKey = `example:${ + testOrganic ? "organic:none" : "tagged:ff" + }`; + let tagged = testOrganic ? "false" : "true"; + let partnerCode = testOrganic ? "" : "ff"; + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + getSERPUrl(getPageUrl(true), testOrganic) + ); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { [expectedContentScalarKey]: 1 }, + "browser.search.withads.unknown": { + [expectedScalarKey.replace("sap", "tagged")]: 1, + }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged, + partner_code: partnerCode, + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + await promiseAdImpressionReceived(1); + + let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser); + BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser); + await pageLoadPromise; + await promiseWaitForAdLinkCheck(); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { [expectedContentScalarKey]: 1 }, + "browser.search.withads.unknown": { [expectedScalarKey]: 1 }, + "browser.search.adclicks.unknown": { [expectedScalarKey]: 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged, + partner_code: partnerCode, + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + }, + ]); + + // Now go back, and click again. + pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser); + gBrowser.goBack(); + await pageLoadPromise; + await promiseWaitForAdLinkCheck(); + + // We've gone back, so we register an extra display & if it is with ads or not. + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.tabhistory": { [expectedContentScalarKey]: 1 }, + "browser.search.content.unknown": { [expectedContentScalarKey]: 1 }, + "browser.search.withads.tabhistory": { [expectedScalarKey]: 1 }, + "browser.search.withads.unknown": { [expectedScalarKey]: 1 }, + "browser.search.adclicks.unknown": { [expectedScalarKey]: 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged, + partner_code: partnerCode, + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + }, + { + impression: { + provider: "example", + tagged, + partner_code: partnerCode, + source: "tabhistory", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + await promiseAdImpressionReceived(2); + + pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser); + BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser); + await pageLoadPromise; + await promiseWaitForAdLinkCheck(); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.tabhistory": { [expectedContentScalarKey]: 1 }, + "browser.search.content.unknown": { [expectedContentScalarKey]: 1 }, + "browser.search.withads.tabhistory": { [expectedScalarKey]: 1 }, + "browser.search.withads.unknown": { [expectedScalarKey]: 1 }, + "browser.search.adclicks.tabhistory": { [expectedScalarKey]: 1 }, + "browser.search.adclicks.unknown": { [expectedScalarKey]: 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged, + partner_code: partnerCode, + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + }, + { + impression: { + provider: "example", + tagged, + partner_code: partnerCode, + source: "tabhistory", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + }, + ]); + + BrowserTestUtils.removeTab(tab); +} + +add_task(async function test_track_ad_click() { + await track_ad_click(false); +}); + +add_task(async function test_track_ad_click_organic() { + await track_ad_click(true); +}); + +add_task(async function test_track_ad_click_with_location_change_other_tab() { + resetTelemetry(); + const url = getSERPUrl(getPageUrl(true)); + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url); + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "example:tagged:ff": 1 }, + "browser.search.withads.unknown": { "example:tagged": 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + }, + ]); + await promiseAdImpressionReceived(); + + const newTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "https://example.com" + ); + + await BrowserTestUtils.switchTab(gBrowser, tab); + + let pageLoadPromise = BrowserTestUtils.waitForLocationChange(gBrowser); + BrowserTestUtils.synthesizeMouseAtCenter("#ad1", {}, tab.linkedBrowser); + await pageLoadPromise; + + await assertSearchSourcesTelemetry( + {}, + { + "browser.search.content.unknown": { "example:tagged:ff": 1 }, + "browser.search.withads.unknown": { "example:tagged": 1 }, + "browser.search.adclicks.unknown": { "example:tagged": 1 }, + } + ); + + assertImpressionEvents([ + { + impression: { + provider: "example", + tagged: "true", + partner_code: "ff", + source: "unknown", + is_shopping_page: "false", + shopping_tab_displayed: "false", + }, + engagements: [ + { + action: SearchSERPTelemetryUtils.ACTIONS.CLICKED, + target: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK, + }, + ], + }, + ]); + + BrowserTestUtils.removeTab(newTab); + BrowserTestUtils.removeTab(tab); +}); -- cgit v1.2.3