commit 61bf0a41d6b50c40cdbef5f02193fbebc1afd77c
parent f10ae21e5ae408e01f7140469f09e4cc87b42d0a
Author: Nathan Barrett <nbarrett@mozilla.com>
Date: Fri, 9 Jan 2026 21:38:07 +0000
Bug 2009413 - Add trainhopConfig values for max conversions and max lookback days r=maxx,home-newtab-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D278519
Diffstat:
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/browser/extensions/newtab/lib/NewTabAttributionService.sys.mjs b/browser/extensions/newtab/lib/NewTabAttributionService.sys.mjs
@@ -10,6 +10,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
DAPSender: "resource://gre/modules/DAPSender.sys.mjs",
ObliviousHTTP: "resource://gre/modules/ObliviousHTTP.sys.mjs",
HPKEConfigManager: "resource://gre/modules/HPKEConfigManager.sys.mjs",
+ AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs",
});
const MAX_CONVERSIONS = 2;
@@ -86,6 +87,13 @@ class NewTabAttributionService {
return this.#dateProvider.now();
}
+ #getTrainhopConfig() {
+ return (
+ lazy.AboutNewTab.activityStream?.store.getState().Prefs.values
+ .trainhopConfig ?? {}
+ );
+ }
+
/**
* onAttributionEvent stores an event locally for an attributable interaction on Newtab.
*
@@ -169,7 +177,15 @@ class NewTabAttributionService {
*/
async onAttributionConversion(partnerId, lookbackDays, impressionType) {
try {
- if (lookbackDays > MAX_LOOKBACK_DAYS) {
+ const trainhopConfig = this.#getTrainhopConfig();
+ const attributionConfig = trainhopConfig.attribution || {};
+
+ const maxLookbackDays =
+ attributionConfig.maxLookbackDays ?? MAX_LOOKBACK_DAYS;
+ const maxConversions =
+ attributionConfig.maxConversions ?? MAX_CONVERSIONS;
+
+ if (lookbackDays > maxLookbackDays) {
return;
}
// we don't want to request the gateway key at time of conversion to avoid an IP address leak
@@ -205,7 +221,7 @@ class NewTabAttributionService {
let measurement = receivedTaskConfig.default_measurement;
let budgetSpend = 0;
- if (budget.conversions < MAX_CONVERSIONS && impression) {
+ if (budget.conversions < maxConversions && impression) {
budgetSpend = 1;
const conversionIndex = impression.conversion.index;
if (
diff --git a/browser/extensions/newtab/test/xpcshell/test_NewTabAttributionService.js b/browser/extensions/newtab/test/xpcshell/test_NewTabAttributionService.js
@@ -7,6 +7,7 @@ ChromeUtils.defineESModuleGetters(this, {
NewTabAttributionServiceClass:
"resource://newtab/lib/NewTabAttributionService.sys.mjs",
ObliviousHTTP: "resource://gre/modules/ObliviousHTTP.sys.mjs",
+ AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs",
sinon: "resource://testing-common/Sinon.sys.mjs",
});
@@ -134,6 +135,22 @@ add_setup(async function () {
});
},
});
+
+ const mockStore = {
+ getState: () => ({
+ Prefs: {
+ values: {
+ trainhopConfig: {
+ attribution: {},
+ },
+ },
+ },
+ }),
+ };
+
+ globalSandbox.stub(AboutNewTab, "activityStream").value({
+ store: mockStore,
+ });
});
registerCleanupFunction(() => {