diff --git a/browser/components/asrouter/docs/targeting-attributes.md b/browser/components/asrouter/docs/targeting-attributes.md index bc24acf93ba0..56ffcb24de36 100644 --- a/browser/components/asrouter/docs/targeting-attributes.md +++ b/browser/components/asrouter/docs/targeting-attributes.md @@ -61,6 +61,7 @@ Please note that some targeting attributes require stricter controls on the tele * [messageImpressions](#messageimpressions) * [needsUpdate](#needsupdate) * [newtabSettings](#newtabsettings) +* [packageFamilyName](#packagefamilyname) * [pinnedSites](#pinnedsites) * [platformName](#platformname) * [previousSessionEnd](#previoussessionend) @@ -371,6 +372,21 @@ Does the client have the latest available version installed declare const needsUpdate: boolean; ``` +### `packageFamilyName` +Provides the package family name as given by the MSIX that Firefox was +installed from, or the empty string if not installed from MSIX. + +#### Examples +* Is the user running MSIX Nightly? +```ts +"MozillaNightly" in packageFamilyName +``` + +#### Definition +```ts +declare const packageFamilyName: string; +``` + ### `pinnedSites` The sites (including search shortcuts) that are pinned on a user's new tab page. diff --git a/browser/components/asrouter/modules/ASRouterTargeting.sys.mjs b/browser/components/asrouter/modules/ASRouterTargeting.sys.mjs index d7d7aa1f5231..cd86ef09fa88 100644 --- a/browser/components/asrouter/modules/ASRouterTargeting.sys.mjs +++ b/browser/components/asrouter/modules/ASRouterTargeting.sys.mjs @@ -975,6 +975,22 @@ const TargetingGetters = { return Services.sysinfo.getProperty("hasWinPackageId", false); }, + get packageFamilyName() { + if (AppConstants.platform !== "win") { + // PackageFamilyNames are an MSIX feature, so they won't be available on non-Windows platforms. + return null; + } + + let packageFamilyName = Services.sysinfo.getProperty( + "winPackageFamilyName" + ); + if (packageFamilyName === "") { + return null; + } + + return packageFamilyName; + }, + /** * Is this invocation running in background task mode? * diff --git a/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js b/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js index 9dc2dada05ce..fb3a166eca1b 100644 --- a/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js +++ b/browser/components/asrouter/tests/browser/browser_asrouter_targeting.js @@ -1570,6 +1570,64 @@ add_task(async function check_isMSIX() { ); }); +add_task(async function check_packageFamilyName() { + if (AppConstants.platform !== "win") { + is( + ASRouterTargeting.Environment.packageFamilyName, + null, + "Should always be null on non-Windows" + ); + return; + } + + let winPackageFamilyName = Services.sysinfo.getProperty( + "winPackageFamilyName" + ); + if (winPackageFamilyName === "") { + is( + ASRouterTargeting.Environment.packageFamilyName, + null, + "Should be null if sysinfo is empty" + ); + } else { + is( + ASRouterTargeting.Environment.packageFamilyName, + winPackageFamilyName, + "Should match non-empty sysinfo" + ); + } +}); + +add_task(async function check_msixConsistency() { + if (ASRouterTargeting.Environment.isMSIX) { + Assert.greater( + ASRouterTargeting.Environment.packageFamilyName.length, + 0, + "packageFamilyName should be non-empty if installed by MSIX" + ); + } else { + is( + ASRouterTargeting.Environment.packageFamilyName, + null, + "packageFamilyName should be empty if not installed by MSIX" + ); + } + + if (ASRouterTargeting.Environment.packageFamilyName === null) { + is( + ASRouterTargeting.Environment.isMSIX, + false, + "isMSIX should be false if packageFamilyName is not present" + ); + } else { + is( + ASRouterTargeting.Environment.isMSIX, + true, + "isMSIX should be true if packageFamilyName is present" + ); + } +}); + add_task(async function check_isRTAMO() { is( typeof ASRouterTargeting.Environment.isRTAMO,