1218 lines
37 KiB
JavaScript
1218 lines
37 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||
|
||
// Test that TelemetryController sends close to shutdown don't lead
|
||
// to AsyncShutdown timeouts.
|
||
|
||
"use strict";
|
||
|
||
ChromeUtils.defineESModuleGetters(this, {
|
||
AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
|
||
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
|
||
sinon: "resource://testing-common/Sinon.sys.mjs",
|
||
WinTaskbarJumpList: "resource:///modules/WindowsJumpLists.sys.mjs",
|
||
TestUtils: "resource://testing-common/TestUtils.sys.mjs",
|
||
});
|
||
|
||
const { NimbusTestUtils } = ChromeUtils.importESModule(
|
||
"resource://testing-common/NimbusTestUtils.sys.mjs"
|
||
);
|
||
const { Policy, TelemetryReportingPolicy } = ChromeUtils.importESModule(
|
||
"resource://gre/modules/TelemetryReportingPolicy.sys.mjs"
|
||
);
|
||
|
||
NimbusTestUtils.init(this);
|
||
|
||
const TOU_ACCEPTED_VERSION_PREF = "termsofuse.acceptedVersion";
|
||
const TOU_CURRENT_VERSION_PREF = "termsofuse.currentVersion";
|
||
const TOU_MINIMUM_VERSION_PREF = "termsofuse.minimumVersion";
|
||
const TOU_ACCEPTED_DATE_PREF = "termsofuse.acceptedDate";
|
||
const TOU_BYPASS_NOTIFICATION_PREF = "termsofuse.bypassNotification";
|
||
|
||
// Some tests in this test file can't outside desktop Firefox because of
|
||
// features that aren't included in the build.
|
||
const skipIfNotBrowser = () => ({
|
||
skip_if: () => AppConstants.MOZ_BUILD_APP != "browser",
|
||
});
|
||
|
||
function fakeResetAcceptedPolicy() {
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_DATE_PREF);
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_VERSION_PREF);
|
||
}
|
||
|
||
// Fake dismissing a modal dialog.
|
||
function fakeInteractWithModal() {
|
||
Services.obs.notifyObservers(null, "termsofuse:interacted");
|
||
// Mark that notification is no longer in progress
|
||
TelemetryReportingPolicy.testNotificationInProgress(false);
|
||
}
|
||
|
||
function unsetMinimumPolicyVersion() {
|
||
Services.prefs.clearUserPref(TOU_MINIMUM_VERSION_PREF);
|
||
}
|
||
|
||
function enrollInPreonboardingExperiment(version) {
|
||
return NimbusTestUtils.enrollWithFeatureConfig(
|
||
{
|
||
featureId: NimbusFeatures.preonboarding.featureId,
|
||
value: {
|
||
enabled: true,
|
||
currentVersion: version,
|
||
minimumVersion: version,
|
||
firstRunURL: `http://mochi.test/v${version}`,
|
||
// Needed to opt into the modal flow, but not actually used in this test.
|
||
screens: [{ id: "test" }],
|
||
},
|
||
},
|
||
{ isRollout: false }
|
||
);
|
||
}
|
||
|
||
add_setup(async function test_setup() {
|
||
// Addon manager needs a profile directory
|
||
do_get_profile(true);
|
||
await loadAddonManager(
|
||
"xpcshell@tests.mozilla.org",
|
||
"XPCShell",
|
||
"1",
|
||
"1.9.2"
|
||
);
|
||
finishAddonManagerStartup();
|
||
fakeIntlReady();
|
||
|
||
// Make sure we don't generate unexpected pings due to pref changes.
|
||
await setEmptyPrefWatchlist();
|
||
|
||
// Don't bypass the legacy data reporting notifications in this test, we'll
|
||
// fake it.
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
false
|
||
);
|
||
|
||
// Don't bypass the terms of use notification in this test, we'll
|
||
// fake it.
|
||
Services.prefs.setBoolPref(TOU_BYPASS_NOTIFICATION_PREF, false);
|
||
await Services.fog.testResetFOG();
|
||
TelemetryReportingPolicy.setup();
|
||
});
|
||
|
||
add_setup(skipIfNotBrowser(), async () => {
|
||
const { cleanup } = await NimbusTestUtils.setupTest();
|
||
registerCleanupFunction(cleanup);
|
||
});
|
||
|
||
add_setup(() => {
|
||
// In head.js, we force TOU pre-onboarding off in xpcshell so Telemetry isn't
|
||
// gated on Browser UI. Revert for these tests.
|
||
const TOS_ENABLED_PREF = "browser.preonboarding.enabled";
|
||
Services.prefs.clearUserPref(TOS_ENABLED_PREF);
|
||
});
|
||
|
||
add_setup(() => {
|
||
// Clean up all potentially modified prefs and reset state after test tasks
|
||
// have run.
|
||
registerCleanupFunction(() => {
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_DATE_PREF);
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_VERSION_PREF);
|
||
Services.prefs.clearUserPref(TOU_BYPASS_NOTIFICATION_PREF);
|
||
Services.prefs.clearUserPref("browser.preonboarding.enabled");
|
||
Services.prefs.clearUserPref("browser.preonboarding.screens");
|
||
Services.prefs.clearUserPref(
|
||
"datareporting.policy.dataSubmissionPolicyNotifiedTime"
|
||
);
|
||
Services.prefs.clearUserPref(
|
||
"datareporting.policy.dataSubmissionPolicyAcceptedVersion"
|
||
);
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.BypassNotification);
|
||
Services.prefs.getDefaultBranch(null).deleteBranch("distribution.id");
|
||
TelemetryReportingPolicy.testNotificationInProgress(false);
|
||
TelemetryReportingPolicy.reset();
|
||
});
|
||
});
|
||
|
||
add_task(skipIfNotBrowser(), async function test_feature_prefs() {
|
||
// Verify that feature values impact Gecko preferences at
|
||
// `sessionstore-windows-restored` time, but not afterward.
|
||
function assertPrefs(currentVersion, minimumVersion, firstRunURL) {
|
||
Assert.equal(
|
||
Services.prefs.getIntPref(TOU_CURRENT_VERSION_PREF),
|
||
currentVersion,
|
||
`${TOU_CURRENT_VERSION_PREF} is set`
|
||
);
|
||
|
||
Assert.equal(
|
||
Services.prefs.getIntPref(TOU_MINIMUM_VERSION_PREF),
|
||
minimumVersion,
|
||
`${TOU_MINIMUM_VERSION_PREF} is set`
|
||
);
|
||
|
||
Assert.equal(
|
||
Services.prefs.getCharPref(TelemetryUtils.Preferences.FirstRunURL),
|
||
firstRunURL,
|
||
"datareporting.policy.firstRunURL is set"
|
||
);
|
||
}
|
||
|
||
unsetMinimumPolicyVersion();
|
||
Services.prefs.clearUserPref(TOU_CURRENT_VERSION_PREF);
|
||
|
||
let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig(
|
||
{
|
||
featureId: NimbusFeatures.preonboarding.featureId,
|
||
value: {
|
||
enabled: true,
|
||
currentVersion: 900,
|
||
minimumVersion: 899,
|
||
firstRunURL: "http://mochi.test/v900",
|
||
},
|
||
},
|
||
{ isRollout: false }
|
||
);
|
||
|
||
Assert.ok(NimbusFeatures.preonboarding.getVariable("enabled"));
|
||
|
||
// Before `sessionstore-windows-restored`, nothing is configured.
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
Assert.ok(
|
||
!Services.prefs.prefHasUserValue(TOU_CURRENT_VERSION_PREF),
|
||
`${TOU_CURRENT_VERSION_PREF} is not set`
|
||
);
|
||
|
||
Assert.ok(
|
||
!Services.prefs.prefHasUserValue(TOU_MINIMUM_VERSION_PREF),
|
||
`${TOU_MINIMUM_VERSION_PREF} is not set`
|
||
);
|
||
|
||
Assert.ok(
|
||
!Services.prefs.prefHasUserValue(TelemetryUtils.Preferences.FirstRunURL),
|
||
"datareporting.policy.firstRunURL is not set"
|
||
);
|
||
|
||
// After `sessionstore-windows-restored`, values are adopted.
|
||
await Policy.fakeSessionRestoreNotification();
|
||
assertPrefs(900, 899, "http://mochi.test/v900");
|
||
|
||
// Unenroll. Values remain, for consistency while Firefox is running.
|
||
await doCleanup();
|
||
Assert.ok(!NimbusFeatures.preonboarding.getVariable("enabled"));
|
||
assertPrefs(900, 899, "http://mochi.test/v900");
|
||
|
||
// Updating the Nimbus feature does nothing (without `sessionstore-windows-restored`).
|
||
doCleanup = await NimbusTestUtils.enrollWithFeatureConfig(
|
||
{
|
||
featureId: NimbusFeatures.preonboarding.featureId,
|
||
value: {
|
||
enabled: true,
|
||
currentVersion: 901,
|
||
minimumVersion: 900,
|
||
firstRunURL: "http://mochi.test/v901",
|
||
},
|
||
},
|
||
{ isRollout: false }
|
||
);
|
||
Assert.ok(NimbusFeatures.preonboarding.getVariable("enabled"));
|
||
assertPrefs(900, 899, "http://mochi.test/v900");
|
||
await doCleanup();
|
||
});
|
||
|
||
async function doOneModalFlow(version) {
|
||
let doCleanup = await enrollInPreonboardingExperiment(version);
|
||
|
||
let displayStub = sinon.stub(Policy, "showModal").returns(true);
|
||
|
||
// This will notify the user via a modal.
|
||
TelemetryReportingPolicy.reset();
|
||
await Policy.fakeSessionRestoreNotification();
|
||
|
||
Assert.equal(displayStub.callCount, 1, "showModal is invoked");
|
||
|
||
Assert.equal(
|
||
TelemetryReportingPolicy.userHasAcceptedTOU(),
|
||
false,
|
||
"Before interaction, the user should be reported as not having accepted"
|
||
);
|
||
|
||
let completed = false;
|
||
let p = TelemetryReportingPolicy.ensureUserIsNotified().then(
|
||
() => (completed = true)
|
||
);
|
||
|
||
Assert.equal(
|
||
completed,
|
||
false,
|
||
"The notification promise should not resolve before the user interacts"
|
||
);
|
||
|
||
fakeInteractWithModal();
|
||
|
||
await p;
|
||
|
||
Assert.equal(
|
||
completed,
|
||
true,
|
||
"The notification promise should resolve after user interacts"
|
||
);
|
||
|
||
Assert.equal(
|
||
TelemetryReportingPolicy.userHasAcceptedTOU(),
|
||
true,
|
||
"After interaction, the state should be accepted."
|
||
);
|
||
|
||
const metricVersion = await Glean.termsofuse.version.testGetValue();
|
||
Assert.equal(
|
||
metricVersion,
|
||
version,
|
||
`Glean.termsofuse.version is ${metricVersion} and matches expected ${version}`
|
||
);
|
||
|
||
const rawDate = await Glean.termsofuse.date.testGetValue();
|
||
// Compare only seconds
|
||
const metricSec = getDateInSeconds(rawDate);
|
||
const expectedSec = getDateInSeconds(
|
||
Services.prefs.getStringPref(TOU_ACCEPTED_DATE_PREF)
|
||
);
|
||
Assert.equal(
|
||
metricSec,
|
||
expectedSec,
|
||
`Glean.termsofuse.date (in seconds) is ${metricSec} and matches expected ${expectedSec}`
|
||
);
|
||
|
||
await doCleanup();
|
||
|
||
sinon.restore();
|
||
}
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_modal_flow_before_notification() {
|
||
// Test the `--first-startup` flow. Suppose the user has not been notified.
|
||
// Verify that when the Nimbus feature is configured, the modal branch is
|
||
// taken, that the ensure promise waits, and that the observer notification
|
||
// resolves the ensure promise.
|
||
|
||
fakeResetAcceptedPolicy();
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.FirstRun);
|
||
|
||
await doOneModalFlow(900);
|
||
|
||
// The user accepted the version from the experiment/rollout.
|
||
Assert.equal(Services.prefs.getIntPref(TOU_ACCEPTED_VERSION_PREF), 900);
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_modal_flow_after_notification() {
|
||
// If the legacy infobar was shown previously (existing users), we never
|
||
// show the TOU modal, even if they’re later enrolled in a Nimbus
|
||
// experiment.
|
||
fakeResetAcceptedPolicy();
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.FirstRun);
|
||
|
||
// Mark user as already notified via the legacy infobar
|
||
TelemetryReportingPolicy.reset();
|
||
TelemetryReportingPolicy.testInfobarShown();
|
||
Assert.ok(
|
||
TelemetryReportingPolicy.testIsUserNotifiedOfDataReportingPolicy(),
|
||
"User is notified after seeing the legacy infobar"
|
||
);
|
||
|
||
let doCleanup = await enrollInPreonboardingExperiment(900);
|
||
|
||
let modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
let p = Policy.delayedSetup();
|
||
Policy.fakeSessionRestoreNotification();
|
||
await p;
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
0,
|
||
"showModal should not be invoked after legacy infobar notification"
|
||
);
|
||
|
||
// Cleanup
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.AcceptedPolicyDate);
|
||
Services.prefs.clearUserPref(
|
||
TelemetryUtils.Preferences.AcceptedPolicyVersion
|
||
);
|
||
TelemetryReportingPolicy.reset();
|
||
await doCleanup();
|
||
sinon.restore();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_default_modal_shows_when_not_enrolled_in_experiment() {
|
||
if (AppConstants.platform === "linux") {
|
||
info(
|
||
"Skipping test for Linux where preonboarding is disabled by default"
|
||
);
|
||
return;
|
||
}
|
||
let modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
|
||
fakeResetAcceptedPolicy();
|
||
TelemetryReportingPolicy.reset();
|
||
let p = Policy.delayedSetup();
|
||
Policy.fakeSessionRestoreNotification();
|
||
fakeInteractWithModal();
|
||
await p;
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
1,
|
||
"showModal is invoked once when not enrolled in an experiemnt"
|
||
);
|
||
|
||
sinon.restore();
|
||
fakeResetAcceptedPolicy();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_modal_not_shown_on_non_eligible_linux() {
|
||
if (AppConstants.platform !== "linux") {
|
||
info("Skipping test on non-Linux platforms");
|
||
return;
|
||
}
|
||
|
||
sinon.stub(Policy, "shouldEnableTOUAtRuntime").returns(false);
|
||
let modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
|
||
fakeResetAcceptedPolicy();
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
let p = Policy.delayedSetup();
|
||
Policy.fakeSessionRestoreNotification();
|
||
await p;
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
0,
|
||
"showModal is not invoked on non-eligible (non-Mozilla Official) Linux"
|
||
);
|
||
|
||
sinon.restore();
|
||
fakeResetAcceptedPolicy();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_modal_shown_on_eligible_linux() {
|
||
if (AppConstants.platform !== "linux") {
|
||
info("Skipping test for non-Linux platform");
|
||
return;
|
||
}
|
||
|
||
sinon.stub(Policy, "shouldEnableTOUAtRuntime").returns(true);
|
||
let modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
|
||
fakeResetAcceptedPolicy();
|
||
TelemetryReportingPolicy.reset();
|
||
await Policy.fakeSessionRestoreNotification();
|
||
|
||
let p = TelemetryReportingPolicy.ensureUserIsNotified();
|
||
fakeInteractWithModal();
|
||
await p;
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
1,
|
||
"showModal is invoked for official Mozilla Linux distributions"
|
||
);
|
||
|
||
Assert.ok(
|
||
TelemetryReportingPolicy.userHasAcceptedTOU(),
|
||
"TOU is accepted after interacting with the modal on eligible Linux"
|
||
);
|
||
|
||
sinon.restore();
|
||
fakeResetAcceptedPolicy();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_jumplist_blocking_on_modal_display_and_unblocking_after_interaction() {
|
||
if (AppConstants.platform !== "win") {
|
||
info("Skipping test for Windows only behavior");
|
||
return;
|
||
}
|
||
|
||
fakeResetAcceptedPolicy();
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.FirstRun);
|
||
let blockSpy = sinon.spy(WinTaskbarJumpList, "blockJumpList");
|
||
let unblockSpy = sinon.spy(WinTaskbarJumpList, "_unblockJumpList");
|
||
sinon.stub(Policy, "showModal").returns(true);
|
||
|
||
let doCleanup = await enrollInPreonboardingExperiment(900);
|
||
|
||
// This will notify the user via a modal.
|
||
TelemetryReportingPolicy.reset();
|
||
await Policy.fakeSessionRestoreNotification();
|
||
|
||
Assert.ok(
|
||
blockSpy.calledOnce,
|
||
"Jump list should be blocked when modal is presented."
|
||
);
|
||
|
||
let p = TelemetryReportingPolicy.ensureUserIsNotified;
|
||
|
||
fakeInteractWithModal();
|
||
|
||
await p;
|
||
|
||
Assert.greaterOrEqual(
|
||
unblockSpy.callCount,
|
||
blockSpy.callCount,
|
||
"Jump list should be unblocked after user interacts with modal"
|
||
);
|
||
|
||
await doCleanup();
|
||
|
||
sinon.restore();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_startup_records_tou_telemetry_if_prefs_already_set() {
|
||
const timestamp = Date.now();
|
||
const version = 999;
|
||
|
||
Services.prefs.setStringPref(TOU_ACCEPTED_DATE_PREF, timestamp.toString());
|
||
Services.prefs.setIntPref(TOU_ACCEPTED_VERSION_PREF, version);
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
const metricVersion = await Glean.termsofuse.version.testGetValue();
|
||
Assert.equal(
|
||
metricVersion,
|
||
version,
|
||
`Glean.termsofuse.version is ${metricVersion} and matches expected ${version}`
|
||
);
|
||
|
||
// Compare only seconds
|
||
const rawDate = await Glean.termsofuse.date.testGetValue();
|
||
const metricSec = getDateInSeconds(rawDate);
|
||
const expectedSec = getDateInSeconds(timestamp);
|
||
Assert.equal(
|
||
metricSec,
|
||
expectedSec,
|
||
`Glean.termsofuse.date (in seconds) is ${metricSec} and matches expected ${expectedSec}`
|
||
);
|
||
|
||
fakeResetAcceptedPolicy();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_user_tou_ineligible_notification() {
|
||
// Simulate a user that is *ineligible* to see the ToU by enabling the
|
||
// bypass-notification pref.
|
||
Services.prefs.setBoolPref(TOU_BYPASS_NOTIFICATION_PREF, true);
|
||
|
||
let doCleanup = await enrollInPreonboardingExperiment(999);
|
||
TelemetryReportingPolicy.reset();
|
||
const modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
|
||
// We expect this event to fire before Policy.delayedSetup resolves,
|
||
// so any change in that is considered a change in behaviour, and we should catch that.
|
||
// This is why we don't await on this promise.
|
||
let notificationSeen = false;
|
||
TestUtils.topicObserved(
|
||
TelemetryReportingPolicy.TELEMETRY_TOU_ACCEPTED_OR_INELIGIBLE
|
||
).then(() => (notificationSeen = true));
|
||
|
||
const p = Policy.delayedSetup();
|
||
Policy.fakeSessionRestoreNotification();
|
||
// Spin the event loop once – the notification should *not* have fired yet.
|
||
await TestUtils.waitForTick();
|
||
await p;
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
0,
|
||
"showModal should never be invoked when the user is ineligible"
|
||
);
|
||
Assert.ok(
|
||
notificationSeen,
|
||
"System is notified it is ok to continue to initialize"
|
||
);
|
||
|
||
// Clean-up.
|
||
// Avoid using clearUserPref here because the default in tests is `true`.
|
||
// Explicitly set the pref to `false` to override the default.
|
||
Services.prefs.setBoolPref(TOU_BYPASS_NOTIFICATION_PREF, false);
|
||
fakeResetAcceptedPolicy();
|
||
await doCleanup();
|
||
sinon.restore();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_user_tou_accepted_previously_notification() {
|
||
// Pretend the user already accepted the ToU in a prior session.
|
||
const timestamp = Date.now();
|
||
const version = 999;
|
||
let doCleanup = await enrollInPreonboardingExperiment(999);
|
||
Services.prefs.setStringPref(TOU_ACCEPTED_DATE_PREF, timestamp.toString());
|
||
Services.prefs.setIntPref(TOU_ACCEPTED_VERSION_PREF, version);
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
const modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
|
||
// We expect this event to fire before Policy.delayedSetup resolves,
|
||
// so any change in that is considered a change in behaviour, and we should catch that.
|
||
// This is why we don't await on this promise.
|
||
let notificationSeen = false;
|
||
TestUtils.topicObserved(
|
||
TelemetryReportingPolicy.TELEMETRY_TOU_ACCEPTED_OR_INELIGIBLE
|
||
).then(() => (notificationSeen = true));
|
||
|
||
let p = Policy.delayedSetup();
|
||
Policy.fakeSessionRestoreNotification();
|
||
await p;
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
0,
|
||
"showModal should not be invoked when the user previously accepted the ToU"
|
||
);
|
||
Assert.ok(
|
||
notificationSeen,
|
||
"System is notified it is ok to continue to initialize"
|
||
);
|
||
|
||
// Clean-up.
|
||
fakeResetAcceptedPolicy();
|
||
await doCleanup();
|
||
sinon.restore();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_user_tou_accepted_now_notification() {
|
||
// User has *not* accepted yet; they will accept via the modal we display.
|
||
const modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
let doCleanup = await enrollInPreonboardingExperiment(999);
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
// We expect this event to fire before Policy.delayedSetup resolves,
|
||
// so any change in that is considered a change in behaviour, and we should catch that.
|
||
// This is why we don't await on this promise.
|
||
let notificationSeen = false;
|
||
TestUtils.topicObserved(
|
||
TelemetryReportingPolicy.TELEMETRY_TOU_ACCEPTED_OR_INELIGIBLE
|
||
).then(() => (notificationSeen = true));
|
||
|
||
let p = Policy.delayedSetup();
|
||
Policy.fakeSessionRestoreNotification();
|
||
// Mark that notification is in progress
|
||
TelemetryReportingPolicy.testNotificationInProgress(true);
|
||
// Spin the event loop once – the notification should *not* have fired yet.
|
||
await TestUtils.waitForTick();
|
||
|
||
Assert.ok(
|
||
!notificationSeen,
|
||
"Notification should not be dispatched before the user interacts"
|
||
);
|
||
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"canUpload() is false while TOU modal is showing (notification in progress)"
|
||
);
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
1,
|
||
"showModal should be invoked exactly once when prompting the user"
|
||
);
|
||
|
||
fakeInteractWithModal();
|
||
await TestUtils.waitForTick();
|
||
await p;
|
||
|
||
Assert.ok(
|
||
TelemetryReportingPolicy.canUpload(),
|
||
"canUpload() is true after the user accepts the TOU via the modal"
|
||
);
|
||
|
||
Assert.ok(
|
||
notificationSeen,
|
||
"Notification fires after the user accepts the ToU in this session"
|
||
);
|
||
|
||
// Clean-up.
|
||
fakeResetAcceptedPolicy();
|
||
TelemetryReportingPolicy.testNotificationInProgress(false);
|
||
await doCleanup();
|
||
sinon.restore();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_user_tou_ignored_no_notification() {
|
||
// User has *not* accepted yet; they will accept via the modal we display.
|
||
const modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
let doCleanup = await enrollInPreonboardingExperiment(999);
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
// We expect this event to fire before Policy.delayedSetup resolves,
|
||
// so any change in that is considered a change in behaviour, and we should catch that.
|
||
// This is why we don't await on this promise.
|
||
let notificationSeen = false;
|
||
TestUtils.topicObserved(
|
||
TelemetryReportingPolicy.TELEMETRY_TOU_ACCEPTED_OR_INELIGIBLE
|
||
).then(() => (notificationSeen = true));
|
||
|
||
let p = Policy.delayedSetup();
|
||
Policy.fakeSessionRestoreNotification();
|
||
// Mark that notification is in progress
|
||
TelemetryReportingPolicy.testNotificationInProgress(true);
|
||
// Spin the event loop once – the notification should *not* have fired yet.
|
||
await TestUtils.waitForTick();
|
||
Assert.ok(
|
||
!notificationSeen,
|
||
"Notification should not be dispatched before the user interacts"
|
||
);
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
1,
|
||
"showModal should be invoked exactly once when prompting the user"
|
||
);
|
||
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"canUpload() is false while TOU modal is showing (notification in progress)"
|
||
);
|
||
|
||
await TestUtils.waitForTick();
|
||
await p;
|
||
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"canUpload() remains false if the user never accepts and no bypass applies"
|
||
);
|
||
|
||
Assert.ok(
|
||
!notificationSeen,
|
||
"Notification should still not be dispatched if never interacted with"
|
||
);
|
||
|
||
// Clean-up.
|
||
fakeResetAcceptedPolicy();
|
||
await doCleanup();
|
||
TelemetryReportingPolicy.testNotificationInProgress(false);
|
||
sinon.restore();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_user_tou_accept_later_notification() {
|
||
// User has *not* accepted yet; they will accept via the modal we display.
|
||
const modalStub = sinon.stub(Policy, "showModal").returns(true);
|
||
let doCleanup = await enrollInPreonboardingExperiment(999);
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
// We expect this event to fire before Policy.delayedSetup resolves,
|
||
// so any change in that is considered a change in behaviour, and we should catch that.
|
||
// This is why we don't await on this promise.
|
||
let notificationSeen = false;
|
||
TestUtils.topicObserved(
|
||
TelemetryReportingPolicy.TELEMETRY_TOU_ACCEPTED_OR_INELIGIBLE
|
||
).then(() => (notificationSeen = true));
|
||
|
||
let p = Policy.delayedSetup();
|
||
Policy.fakeSessionRestoreNotification();
|
||
// Mark that notification is in progress
|
||
TelemetryReportingPolicy.testNotificationInProgress(true);
|
||
// Spin the event loop once – the notification should *not* have fired yet.
|
||
await TestUtils.waitForTick();
|
||
Assert.ok(
|
||
!notificationSeen,
|
||
"Notification should not be dispatched before the user interacts"
|
||
);
|
||
|
||
Assert.equal(
|
||
modalStub.callCount,
|
||
1,
|
||
"showModal should be invoked exactly once when prompting the user"
|
||
);
|
||
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"canUpload() is false while modal is displayed"
|
||
);
|
||
|
||
await TestUtils.waitForTick();
|
||
await p;
|
||
|
||
Assert.ok(
|
||
!notificationSeen,
|
||
"Notification should still not be dispatched if never interacted with"
|
||
);
|
||
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"canUpload() remains false"
|
||
);
|
||
|
||
fakeInteractWithModal();
|
||
await TestUtils.waitForTick();
|
||
|
||
Assert.ok(
|
||
TelemetryReportingPolicy.canUpload(),
|
||
"canUpload() becomes true after later acceptance"
|
||
);
|
||
|
||
Assert.ok(
|
||
notificationSeen,
|
||
"Notification fires after the user accepts the ToU in this session"
|
||
);
|
||
|
||
// Clean-up.
|
||
fakeResetAcceptedPolicy();
|
||
TelemetryReportingPolicy.testNotificationInProgress(false);
|
||
await doCleanup();
|
||
sinon.restore();
|
||
}
|
||
);
|
||
|
||
// Regression test for Bug 1977258: AboutNewTab.init() must set the AS
|
||
// telemetry pref default even when TOU has not yet been accepted, so that
|
||
// about:welcome's first-screen impression is not dropped.
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_as_telemetry_pref_set_before_tou_acceptance() {
|
||
const { AboutNewTab } = ChromeUtils.importESModule(
|
||
"resource:///modules/AboutNewTab.sys.mjs"
|
||
);
|
||
const ACTIVITY_STREAM_TELEMETRY_PREF =
|
||
"browser.newtabpage.activity-stream.telemetry";
|
||
|
||
// Reset any state so we can observe AboutNewTab.init() setting the pref.
|
||
AboutNewTab.uninit();
|
||
Services.prefs
|
||
.getDefaultBranch("")
|
||
.deleteBranch(ACTIVITY_STREAM_TELEMETRY_PREF);
|
||
Services.prefs.clearUserPref(ACTIVITY_STREAM_TELEMETRY_PREF);
|
||
Assert.equal(
|
||
Services.prefs.getPrefType(ACTIVITY_STREAM_TELEMETRY_PREF),
|
||
Services.prefs.PREF_INVALID,
|
||
"ActivityStream telemetry pref is unset before AboutNewTab.init()"
|
||
);
|
||
|
||
sinon.stub(Policy, "showModal").returns(true);
|
||
const doCleanup = await enrollInPreonboardingExperiment(999);
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
try {
|
||
AboutNewTab.init();
|
||
|
||
Assert.equal(
|
||
Services.prefs
|
||
.getDefaultBranch("")
|
||
.getBoolPref(ACTIVITY_STREAM_TELEMETRY_PREF),
|
||
AppConstants.MOZILLA_OFFICIAL,
|
||
"ActivityStream telemetry pref default is set by AboutNewTab.init()"
|
||
);
|
||
} finally {
|
||
AboutNewTab.uninit();
|
||
Services.prefs
|
||
.getDefaultBranch("")
|
||
.deleteBranch(ACTIVITY_STREAM_TELEMETRY_PREF);
|
||
await doCleanup();
|
||
sinon.restore();
|
||
}
|
||
}
|
||
);
|
||
|
||
add_task(async function test_canUpload_unblocked_by_tou_accepted() {
|
||
// On non-Win/Mac platforms, TOU is disabled by default; stub
|
||
// shouldEnableTOUAtRuntime to enable TOU.
|
||
if (AppConstants.platform === "linux") {
|
||
sinon.stub(Policy, "shouldEnableTOUAtRuntime").returns(true);
|
||
}
|
||
|
||
const cleanup = () => {
|
||
sinon.restore();
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.BypassNotification);
|
||
Services.prefs.clearUserPref("termsofuse.acceptedDate");
|
||
Services.prefs.clearUserPref("termsofuse.acceptedVersion");
|
||
TelemetryReportingPolicy.reset();
|
||
};
|
||
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
false
|
||
);
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"Before accepting TOU legacy upload is blocked"
|
||
);
|
||
|
||
Assert.ok(
|
||
!Services.prefs.getIntPref(
|
||
"datareporting.policy.dataSubmissionPolicyAcceptedVersion",
|
||
0
|
||
),
|
||
"Legacy policy flow accepted version not set"
|
||
);
|
||
|
||
Assert.ok(
|
||
!Services.prefs.getBoolPref(
|
||
"datareporting.policy.dataSubmissionPolicyNotifiedTime",
|
||
0
|
||
),
|
||
"Legacy policy flow accepted date not set"
|
||
);
|
||
|
||
Services.prefs.setStringPref("termsofuse.acceptedDate", String(Date.now()));
|
||
Services.prefs.setIntPref(
|
||
"termsofuse.acceptedVersion",
|
||
Services.prefs.getIntPref(TOU_CURRENT_VERSION_PREF, 4)
|
||
);
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
Assert.ok(
|
||
TelemetryReportingPolicy.userHasAcceptedTOU(),
|
||
"TOU acceptance is recorded"
|
||
);
|
||
|
||
Assert.ok(TelemetryReportingPolicy.canUpload(), "Legacy upload allowed");
|
||
|
||
cleanup();
|
||
});
|
||
|
||
add_task(async function test_canUpload_allowed_when_both_bypass_prefs_true() {
|
||
const cleanup = () => {
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.BypassNotification);
|
||
Services.prefs.clearUserPref("termsofuse.bypassNotification");
|
||
Services.prefs.clearUserPref("browser.preonboarding.enabled");
|
||
TelemetryReportingPolicy.reset();
|
||
};
|
||
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
true
|
||
);
|
||
Services.prefs.setBoolPref("termsofuse.bypassNotification", true);
|
||
Services.prefs.setBoolPref("browser.preonboarding.enabled", true);
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
Assert.ok(
|
||
TelemetryReportingPolicy.canUpload(),
|
||
"Upload allowed when both legacy and TOU notification flows are bypassed"
|
||
);
|
||
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
true
|
||
);
|
||
Services.prefs.setBoolPref("termsofuse.bypassNotification", false);
|
||
Services.prefs.setBoolPref("browser.preonboarding.enabled", true);
|
||
Services.prefs.setBoolPref("browser.preonboarding.screens", []);
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"Upload not allowed when only legacy bypass is true and TOU should show"
|
||
);
|
||
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
false
|
||
);
|
||
Services.prefs.setBoolPref("termsofuse.bypassNotification", true);
|
||
// Force TOU enabled so we’re not falling back to legacy notification (on
|
||
// Linux, this is false by default).
|
||
Services.prefs.setBoolPref("browser.preonboarding.enabled", true);
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"Upload blocked when only TOU bypass is true and TOU should show"
|
||
);
|
||
|
||
cleanup();
|
||
});
|
||
|
||
add_task(async function test_canUpload_reconfigures_when_nimbus_not_ready() {
|
||
const cleanup = () => {
|
||
Services.prefs.clearUserPref("browser.preonboarding.enabled");
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.BypassNotification);
|
||
Services.prefs.clearUserPref(TOU_BYPASS_NOTIFICATION_PREF);
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_VERSION_PREF);
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_DATE_PREF);
|
||
sinon.restore();
|
||
TelemetryReportingPolicy.reset();
|
||
};
|
||
|
||
// Force a path where canUpload() must consult Nimbus
|
||
Services.prefs.setBoolPref("browser.preonboarding.enabled", true);
|
||
Services.prefs.setBoolPref(TOU_BYPASS_NOTIFICATION_PREF, false);
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
true
|
||
);
|
||
|
||
const getVarsSpy = sinon
|
||
.stub(NimbusFeatures.preonboarding, "getAllVariables")
|
||
.returns({ enabled: false });
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
const result = TelemetryReportingPolicy.canUpload();
|
||
|
||
Assert.equal(
|
||
getVarsSpy.callCount,
|
||
1,
|
||
"canUpload() should trigger _configureFromNimbus() when variables are not yet set"
|
||
);
|
||
|
||
Assert.ok(
|
||
result,
|
||
"With Nimbus enabled=false, TOU is off; legacy bypass allows upload"
|
||
);
|
||
|
||
cleanup();
|
||
});
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_legacy_bypass_blocked_when_TOU_should_show_and_not_accepted() {
|
||
const cleanup = async () => {
|
||
Services.prefs.clearUserPref("browser.preonboarding.enabled");
|
||
Services.prefs.clearUserPref(
|
||
TelemetryUtils.Preferences.BypassNotification
|
||
);
|
||
Services.prefs.clearUserPref(TOU_BYPASS_NOTIFICATION_PREF);
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_VERSION_PREF);
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_DATE_PREF);
|
||
Services.prefs.clearUserPref(
|
||
"datareporting.policy.dataSubmissionPolicyNotifiedTime"
|
||
);
|
||
Services.prefs.clearUserPref(
|
||
"datareporting.policy.dataSubmissionPolicyAcceptedVersion"
|
||
);
|
||
TelemetryReportingPolicy.reset();
|
||
await unenroll();
|
||
};
|
||
|
||
// Legacy bypass ON, TOU bypass OFF
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
true
|
||
);
|
||
Services.prefs.setBoolPref(TOU_BYPASS_NOTIFICATION_PREF, false);
|
||
|
||
// User has NOT accepted TOU
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_VERSION_PREF);
|
||
Services.prefs.clearUserPref(TOU_ACCEPTED_DATE_PREF);
|
||
|
||
// User has NOT accepted via Legacy flow
|
||
Services.prefs.clearUserPref(
|
||
"datareporting.policy.dataSubmissionPolicyNotifiedTime"
|
||
);
|
||
Services.prefs.clearUserPref(
|
||
"datareporting.policy.dataSubmissionPolicyAcceptedVersion"
|
||
);
|
||
|
||
// Make _shouldShowTOU() return true
|
||
Services.prefs.setBoolPref("browser.preonboarding.enabled", true);
|
||
const unenroll = await NimbusTestUtils.enrollWithFeatureConfig(
|
||
{
|
||
featureId: NimbusFeatures.preonboarding.featureId,
|
||
value: {
|
||
enabled: true,
|
||
currentVersion: 4,
|
||
minimumVersion: 4,
|
||
screens: [{ id: "test" }],
|
||
},
|
||
},
|
||
{ isRollout: false }
|
||
);
|
||
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
const result = TelemetryReportingPolicy.canUpload();
|
||
|
||
Assert.ok(
|
||
!result,
|
||
"When TOU flow should be shown, but is not yet accepted with legacy bypass true, (!shouldShowTOU && bypassLegacy) is false, so upload is blocked."
|
||
);
|
||
|
||
await cleanup();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_linux_tou_eligible_blocks_upload_before_acceptance() {
|
||
Services.prefs.setBoolPref("browser.preonboarding.enabled", false);
|
||
Services.prefs.setBoolPref(TOU_BYPASS_NOTIFICATION_PREF, false);
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
true
|
||
);
|
||
sinon.stub(Policy, "shouldEnableTOUAtRuntime").returns(true);
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
Assert.ok(
|
||
!TelemetryReportingPolicy.canUpload(),
|
||
"TOU blocks upload for Mozilla Linux distro when not yet accepted"
|
||
);
|
||
|
||
sinon.restore();
|
||
Services.prefs.clearUserPref("browser.preonboarding.enabled");
|
||
Services.prefs.clearUserPref(TOU_BYPASS_NOTIFICATION_PREF);
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.BypassNotification);
|
||
TelemetryReportingPolicy.reset();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_linux_tou_eligible_allows_upload_after_acceptance() {
|
||
Services.prefs.setBoolPref("browser.preonboarding.enabled", false);
|
||
Services.prefs.setBoolPref(TOU_BYPASS_NOTIFICATION_PREF, false);
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
true
|
||
);
|
||
Services.prefs.setStringPref(TOU_ACCEPTED_DATE_PREF, String(Date.now()));
|
||
Services.prefs.setIntPref(TOU_ACCEPTED_VERSION_PREF, 4);
|
||
sinon.stub(Policy, "shouldEnableTOUAtRuntime").returns(true);
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
Assert.ok(
|
||
TelemetryReportingPolicy.canUpload(),
|
||
"Upload allowed for Mozilla Linux distro after TOU is acepted"
|
||
);
|
||
|
||
sinon.restore();
|
||
Services.prefs.clearUserPref("browser.preonboarding.enabled");
|
||
Services.prefs.clearUserPref(TOU_BYPASS_NOTIFICATION_PREF);
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.BypassNotification);
|
||
fakeResetAcceptedPolicy();
|
||
TelemetryReportingPolicy.reset();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_linux_non_mozilla_distro_upload_unblocked() {
|
||
Services.prefs.setBoolPref("browser.preonboarding.enabled", false);
|
||
Services.prefs.setBoolPref(
|
||
TelemetryUtils.Preferences.BypassNotification,
|
||
true
|
||
);
|
||
sinon.stub(Policy, "shouldEnableTOUAtRuntime").returns(false);
|
||
TelemetryReportingPolicy.reset();
|
||
|
||
Assert.ok(
|
||
TelemetryReportingPolicy.canUpload(),
|
||
"TOU should not block upload for non-Mozilla Linux distro"
|
||
);
|
||
|
||
sinon.restore();
|
||
Services.prefs.clearUserPref("browser.preonboarding.enabled");
|
||
Services.prefs.clearUserPref(TelemetryUtils.Preferences.BypassNotification);
|
||
TelemetryReportingPolicy.reset();
|
||
}
|
||
);
|
||
|
||
add_task(
|
||
skipIfNotBrowser(),
|
||
async function test_showModal_passes_browser_element_to_handleAction() {
|
||
const { BrowserWindowTracker } = ChromeUtils.importESModule(
|
||
"resource:///modules/BrowserWindowTracker.sys.mjs"
|
||
);
|
||
const { SpecialMessageActions } = ChromeUtils.importESModule(
|
||
"resource://messaging-system/lib/SpecialMessageActions.sys.mjs"
|
||
);
|
||
|
||
const browser = {};
|
||
const win = { gBrowser: { selectedBrowser: browser } };
|
||
|
||
sinon.stub(BrowserWindowTracker, "getTopWindow").returns(win);
|
||
const handleActionStub = sinon
|
||
.stub(SpecialMessageActions, "handleAction")
|
||
.resolves();
|
||
|
||
await Policy.showModal({
|
||
id: "TEST_MODAL",
|
||
screens: [{ id: "SCREEN_1" }],
|
||
requireAction: true,
|
||
});
|
||
|
||
Assert.equal(handleActionStub.callCount, 1, "handleAction called once");
|
||
Assert.strictEqual(
|
||
handleActionStub.firstCall.args[1],
|
||
browser,
|
||
"handleAction receives win.gBrowser.selectedBrowser"
|
||
);
|
||
Assert.notEqual(
|
||
handleActionStub.firstCall.args[1],
|
||
win,
|
||
"handleAction does not receive the chrome window"
|
||
);
|
||
|
||
sinon.restore();
|
||
}
|
||
);
|
||
|
||
add_task(async function test_shouldEnableTOUAtRuntime() {
|
||
const defaultBranch = Services.prefs.getDefaultBranch(null);
|
||
|
||
if (AppConstants.platform !== "linux") {
|
||
defaultBranch.setCharPref("distribution.id", "mozilla-official");
|
||
Assert.ok(
|
||
!Policy.shouldEnableTOUAtRuntime(),
|
||
"shouldEnableTOUAtRuntime() is always false on non-Linux platforms"
|
||
);
|
||
defaultBranch.deleteBranch("distribution.id");
|
||
return;
|
||
}
|
||
|
||
for (const [id, expected] of [
|
||
["mozilla-official", true],
|
||
["mozilla-flatpak", true],
|
||
["mozilla-rpm", true],
|
||
["mozilla-deb", true],
|
||
["mozilla-EMEfree", true],
|
||
["mozilla139", true],
|
||
["canonical-002", false],
|
||
["mint-001", false],
|
||
["redhat", false],
|
||
["fedora", false],
|
||
["", false],
|
||
]) {
|
||
defaultBranch.setCharPref("distribution.id", id);
|
||
Assert.equal(
|
||
Policy.shouldEnableTOUAtRuntime(),
|
||
expected,
|
||
`shouldEnableTOUAtRuntime() is ${expected} for distribution.id "${id}"`
|
||
);
|
||
}
|
||
|
||
defaultBranch.deleteBranch("distribution.id");
|
||
});
|