forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			323 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			323 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* Any copyright is dedicated to the Public Domain.
 | |
|  * http://creativecommons.org/publicdomain/zero/1.0/ */
 | |
| 
 | |
| ChromeUtils.defineModuleGetter(
 | |
|   this,
 | |
|   "Preferences",
 | |
|   "resource://gre/modules/Preferences.jsm"
 | |
| );
 | |
| 
 | |
| const { ExperimentFakes } = ChromeUtils.import(
 | |
|   "resource://testing-common/NimbusTestUtils.jsm"
 | |
| );
 | |
| const { TelemetryTestUtils } = ChromeUtils.import(
 | |
|   "resource://testing-common/TelemetryTestUtils.jsm"
 | |
| );
 | |
| 
 | |
| const PREF_DFPI_ENABLED_BY_DEFAULT =
 | |
|   "privacy.restrict3rdpartystorage.rollout.enabledByDefault";
 | |
| const PREF_DFPI_ROLLOUT_UI_ENABLED =
 | |
|   "privacy.restrict3rdpartystorage.rollout.preferences.TCPToggleInStandard";
 | |
| const COOKIE_BEHAVIOR_PREF = "network.cookie.cookieBehavior";
 | |
| const CAT_PREF = "browser.contentblocking.category";
 | |
| 
 | |
| const LEARN_MORE_URL =
 | |
|   Services.urlFormatter.formatURLPref("app.support.baseURL") +
 | |
|   Services.prefs.getStringPref(
 | |
|     "privacy.restrict3rdpartystorage.rollout.preferences.learnMoreURLSuffix"
 | |
|   );
 | |
| 
 | |
| const {
 | |
|   BEHAVIOR_REJECT_TRACKER,
 | |
|   BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
 | |
| } = Ci.nsICookieService;
 | |
| 
 | |
| function testTelemetryState(optIn) {
 | |
|   let expectedValue;
 | |
|   if (optIn == null) {
 | |
|     expectedValue = 2;
 | |
|   } else {
 | |
|     expectedValue = optIn ? 1 : 0;
 | |
|   }
 | |
| 
 | |
|   TelemetryTestUtils.assertScalar(
 | |
|     TelemetryTestUtils.getProcessScalars("parent"),
 | |
|     "privacy.dfpi_rollout_enabledByDefault",
 | |
|     expectedValue,
 | |
|     "Scalar should have correct value"
 | |
|   );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Waits for preference to be set and asserts the value.
 | |
|  * @param {string} pref - Preference key.
 | |
|  * @param {*} expectedValue - Expected value of the preference.
 | |
|  * @param {string} message - Assertion message.
 | |
|  */
 | |
| async function waitForAndAssertPrefState(pref, expectedValue, message) {
 | |
|   await TestUtils.waitForPrefChange(pref, value => {
 | |
|     if (value != expectedValue) {
 | |
|       return false;
 | |
|     }
 | |
|     is(value, expectedValue, message);
 | |
|     return true;
 | |
|   });
 | |
| }
 | |
| 
 | |
| add_task(async function setup() {
 | |
|   const defaultPrefs = Services.prefs.getDefaultBranch("");
 | |
|   const previousDefaultCB = defaultPrefs.getIntPref(COOKIE_BEHAVIOR_PREF);
 | |
| 
 | |
|   registerCleanupFunction(function() {
 | |
|     defaultPrefs.setIntPref(COOKIE_BEHAVIOR_PREF, previousDefaultCB);
 | |
|   });
 | |
|   defaultPrefs.setIntPref(
 | |
|     COOKIE_BEHAVIOR_PREF,
 | |
|     Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER
 | |
|   );
 | |
| });
 | |
| 
 | |
| async function testRolloutUI({
 | |
|   dFPIEnabledByDefault,
 | |
|   rolloutUIEnabled,
 | |
|   rolloutUIEnabledByExperiment,
 | |
| }) {
 | |
|   info(
 | |
|     "Testing TCP preferences rollout UI " +
 | |
|       JSON.stringify({ dFPIEnabledByDefault, rolloutUIEnabled })
 | |
|   );
 | |
| 
 | |
|   // Initially the rollout pref is not set. Telemetry should record this unset
 | |
|   // state.
 | |
|   testTelemetryState(null);
 | |
| 
 | |
|   // Setting to standard category explicitly, since changing the default cookie
 | |
|   // behavior still switches us to custom initially.
 | |
|   let set = [[CAT_PREF, "standard"]];
 | |
|   if (dFPIEnabledByDefault) {
 | |
|     set.push([PREF_DFPI_ENABLED_BY_DEFAULT, true]);
 | |
|   }
 | |
|   if (rolloutUIEnabled) {
 | |
|     set.push([PREF_DFPI_ROLLOUT_UI_ENABLED, true]);
 | |
|   }
 | |
|   await SpecialPowers.pushPrefEnv({ set });
 | |
| 
 | |
|   // At this point the pref can only be enabled or unset.
 | |
|   testTelemetryState(dFPIEnabledByDefault || null);
 | |
| 
 | |
|   const uiEnabled =
 | |
|     rolloutUIEnabled ||
 | |
|     rolloutUIEnabledByExperiment ||
 | |
|     (dFPIEnabledByDefault &&
 | |
|       Services.prefs.prefHasUserValue(PREF_DFPI_ENABLED_BY_DEFAULT));
 | |
| 
 | |
|   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
 | |
|   let doc = gBrowser.contentDocument;
 | |
| 
 | |
|   let standardRadioOption = doc.getElementById("standardRadio");
 | |
|   let strictRadioOption = doc.getElementById("strictRadio");
 | |
|   let customRadioOption = doc.getElementById("customRadio");
 | |
| 
 | |
|   ok(standardRadioOption.selected, "Standard category is selected");
 | |
| 
 | |
|   is(
 | |
|     Services.prefs.getIntPref(COOKIE_BEHAVIOR_PREF),
 | |
|     dFPIEnabledByDefault
 | |
|       ? BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN
 | |
|       : BEHAVIOR_REJECT_TRACKER,
 | |
|     `dFPI is ${dFPIEnabledByDefault ? "enabled" : "disabled"}.`
 | |
|   );
 | |
| 
 | |
|   let etpStandardTCPRolloutBox = doc.getElementById("etpStandardTCPRolloutBox");
 | |
|   is(
 | |
|     BrowserTestUtils.is_visible(etpStandardTCPRolloutBox),
 | |
|     uiEnabled,
 | |
|     `Rollout UI in standard is ${uiEnabled ? " " : "not "}visible.`
 | |
|   );
 | |
| 
 | |
|   if (uiEnabled) {
 | |
|     // Test the TCP rollout section.
 | |
|     let learnMoreLink = etpStandardTCPRolloutBox.querySelector(
 | |
|       "#tcp-rollout-learn-more-link"
 | |
|     );
 | |
|     ok(learnMoreLink, "Should have a learn more link");
 | |
|     BrowserTestUtils.is_visible(
 | |
|       learnMoreLink,
 | |
|       "Learn more link should be visible."
 | |
|     );
 | |
|     ok(
 | |
|       learnMoreLink.href && !learnMoreLink.href.startsWith("about:blank"),
 | |
|       "Learn more link should be valid"
 | |
|     );
 | |
|     is(
 | |
|       learnMoreLink.href,
 | |
|       LEARN_MORE_URL,
 | |
|       "Learn more link should have the right target."
 | |
|     );
 | |
| 
 | |
|     let description = etpStandardTCPRolloutBox.querySelector(
 | |
|       ".tail-with-learn-more"
 | |
|     );
 | |
|     ok(description, "Should have a description element.");
 | |
|     BrowserTestUtils.is_visible(description, "Description should be visible.");
 | |
| 
 | |
|     is(
 | |
|       BrowserTestUtils.is_visible(etpStandardTCPRolloutBox),
 | |
|       uiEnabled,
 | |
|       `Rollout UI in standard is ${uiEnabled ? " " : "not "}visible.`
 | |
|     );
 | |
| 
 | |
|     // Test the checkbox which toggles TCP in standard mode.
 | |
|     let checkbox = doc.getElementById("etpStandardTCPRollout");
 | |
| 
 | |
|     ok(checkbox, "Should have a checkbox.");
 | |
|     BrowserTestUtils.is_visible(checkbox, "TCP checkbox should be visible.");
 | |
|     ok(checkbox.label, "Checkbox should have a label.");
 | |
| 
 | |
|     let [reloadWarning] = doc.getElementsByClassName(
 | |
|       "content-blocking-reload-description"
 | |
|     );
 | |
|     ok(
 | |
|       !BrowserTestUtils.is_visible(reloadWarning),
 | |
|       "No reload warning initially."
 | |
|     );
 | |
| 
 | |
|     is(
 | |
|       checkbox.checked,
 | |
|       dFPIEnabledByDefault,
 | |
|       "Initial checkbox state reflects dFPI rollout pref state"
 | |
|     );
 | |
| 
 | |
|     // If checkbox is not active initially, check it now and assert pref state.
 | |
|     if (!dFPIEnabledByDefault) {
 | |
|       let prefChangeDFPIByDefault = waitForAndAssertPrefState(
 | |
|         PREF_DFPI_ENABLED_BY_DEFAULT,
 | |
|         true,
 | |
|         "Checkbox should set " + PREF_DFPI_ENABLED_BY_DEFAULT
 | |
|       );
 | |
|       let prefChangeCookieBehavior = waitForAndAssertPrefState(
 | |
|         COOKIE_BEHAVIOR_PREF,
 | |
|         BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
 | |
|         "Checkbox should set " + COOKIE_BEHAVIOR_PREF
 | |
|       );
 | |
|       checkbox.click();
 | |
|       await prefChangeDFPIByDefault;
 | |
|       await prefChangeCookieBehavior;
 | |
|       is(
 | |
|         Services.prefs.getStringPref(CAT_PREF),
 | |
|         "standard",
 | |
|         "Should still be in standard category"
 | |
|       );
 | |
|       ok(
 | |
|         BrowserTestUtils.is_visible(reloadWarning),
 | |
|         "Reload warning should be visible."
 | |
|       );
 | |
|       testTelemetryState(true);
 | |
|     }
 | |
| 
 | |
|     // Un-check checkbox and assert pref state.
 | |
|     let prefChangeDFPIByDefault = waitForAndAssertPrefState(
 | |
|       PREF_DFPI_ENABLED_BY_DEFAULT,
 | |
|       false,
 | |
|       "Checkbox should set " + PREF_DFPI_ENABLED_BY_DEFAULT
 | |
|     );
 | |
|     let prefChangeCookieBehavior = waitForAndAssertPrefState(
 | |
|       COOKIE_BEHAVIOR_PREF,
 | |
|       BEHAVIOR_REJECT_TRACKER,
 | |
|       "Checkbox should set " + COOKIE_BEHAVIOR_PREF
 | |
|     );
 | |
|     checkbox.click();
 | |
|     await prefChangeDFPIByDefault;
 | |
|     await prefChangeCookieBehavior;
 | |
|     is(
 | |
|       Services.prefs.getStringPref(CAT_PREF),
 | |
|       "standard",
 | |
|       "Should still be in standard category"
 | |
|     );
 | |
|     ok(
 | |
|       BrowserTestUtils.is_visible(reloadWarning),
 | |
|       "Reload warning should be visible."
 | |
|     );
 | |
|     testTelemetryState(false);
 | |
|   }
 | |
| 
 | |
|   let categoryPrefChange = waitForAndAssertPrefState(CAT_PREF, "strict");
 | |
|   strictRadioOption.click();
 | |
|   await categoryPrefChange;
 | |
|   ok(
 | |
|     !BrowserTestUtils.is_visible(etpStandardTCPRolloutBox),
 | |
|     "When strict is selected rollout UI is not visible."
 | |
|   );
 | |
| 
 | |
|   categoryPrefChange = waitForAndAssertPrefState(CAT_PREF, "custom");
 | |
|   customRadioOption.click();
 | |
|   await categoryPrefChange;
 | |
|   ok(
 | |
|     !BrowserTestUtils.is_visible(etpStandardTCPRolloutBox),
 | |
|     "When custom is selected rollout UI is not visible."
 | |
|   );
 | |
| 
 | |
|   // Switch back to standard and test if we show the rollout UI again.
 | |
|   categoryPrefChange = waitForAndAssertPrefState(CAT_PREF, "standard");
 | |
|   standardRadioOption.click();
 | |
|   await categoryPrefChange;
 | |
|   is(
 | |
|     BrowserTestUtils.is_visible(etpStandardTCPRolloutBox),
 | |
|     uiEnabled,
 | |
|     `Rollout UI in standard is ${uiEnabled ? " " : "not "}visible.`
 | |
|   );
 | |
| 
 | |
|   gBrowser.removeCurrentTab();
 | |
|   await SpecialPowers.popPrefEnv();
 | |
|   Services.prefs.setStringPref(CAT_PREF, "standard");
 | |
|   Services.prefs.clearUserPref(PREF_DFPI_ENABLED_BY_DEFAULT);
 | |
|   Services.prefs.clearUserPref(PREF_DFPI_ROLLOUT_UI_ENABLED);
 | |
| 
 | |
|   testTelemetryState(null);
 | |
| }
 | |
| 
 | |
| // Clients which are not part of the rollout. They should not see the
 | |
| // preferences UI.
 | |
| add_task(async function test_rollout_ui_disabled() {
 | |
|   await testRolloutUI({ dFPIEnabledByDefault: false, rolloutUIEnabled: false });
 | |
| });
 | |
| 
 | |
| // Clients which are part of the rollout, user opted-in to dFPI in standard.
 | |
| // They should see the preferences UI with the checkbox checked.
 | |
| add_task(async function test_rollout_ui_enabled() {
 | |
|   await testRolloutUI({ dFPIEnabledByDefault: true, rolloutUIEnabled: true });
 | |
| });
 | |
| 
 | |
| // Clients which are part of the rollout, user didn't opt-in to dFPI in
 | |
| // standard. e.g. they dismissed the onboarding dialog.
 | |
| // They should see the preferences UI with the checkbox unchecked.
 | |
| add_task(async function test_rollout_ui_enabled_dfpi_disabled() {
 | |
|   await testRolloutUI({ dFPIEnabledByDefault: false, rolloutUIEnabled: true });
 | |
| });
 | |
| 
 | |
| add_task(async function test_rollout_ui_enabled_by_nimbus() {
 | |
|   await testRolloutUI({
 | |
|     dFPIEnabledByDefault: false,
 | |
|     rolloutUIEnabled: false,
 | |
|     rolloutUIEnabledByExperiment: false,
 | |
|   });
 | |
| 
 | |
|   let doCleanup = await ExperimentFakes.enrollWithFeatureConfig({
 | |
|     featureId: "tcpPreferences",
 | |
|     value: { enabled: true },
 | |
|   });
 | |
| 
 | |
|   await testRolloutUI({
 | |
|     dFPIEnabledByDefault: false,
 | |
|     rolloutUIEnabled: false,
 | |
|     rolloutUIEnabledByExperiment: true,
 | |
|   });
 | |
| 
 | |
|   await doCleanup();
 | |
| 
 | |
|   await testRolloutUI({
 | |
|     dFPIEnabledByDefault: false,
 | |
|     rolloutUIEnabled: false,
 | |
|     rolloutUIEnabledByExperiment: false,
 | |
|   });
 | |
| });
 | 
