tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_datachoices_notification.js (8763B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 var { Preferences } = ChromeUtils.importESModule(
      8  "resource://gre/modules/Preferences.sys.mjs"
      9 );
     10 var { TelemetryReportingPolicy } = ChromeUtils.importESModule(
     11  "resource://gre/modules/TelemetryReportingPolicy.sys.mjs"
     12 );
     13 
     14 const PREF_BRANCH = "datareporting.policy.";
     15 const PREF_FIRST_RUN = "toolkit.telemetry.reportingpolicy.firstRun";
     16 const PREF_BYPASS_NOTIFICATION =
     17  PREF_BRANCH + "dataSubmissionPolicyBypassNotification";
     18 const PREF_CURRENT_POLICY_VERSION = PREF_BRANCH + "currentPolicyVersion";
     19 const PREF_ACCEPTED_POLICY_VERSION =
     20  PREF_BRANCH + "dataSubmissionPolicyAcceptedVersion";
     21 const PREF_ACCEPTED_POLICY_DATE =
     22  PREF_BRANCH + "dataSubmissionPolicyNotifiedTime";
     23 const PREF_TOS_ROLLOUT_POPULATION =
     24  "browser.preonboarding.onTrainRolloutPopulation";
     25 const PREF_TOS_ENABLED = "browser.preonboarding.enabled";
     26 
     27 const PREF_TELEMETRY_LOG_LEVEL = "toolkit.telemetry.log.level";
     28 
     29 const TEST_POLICY_VERSION = 37;
     30 
     31 function fakeShowPolicyTimeout(set, clear) {
     32  let reportingPolicy = ChromeUtils.importESModule(
     33    "resource://gre/modules/TelemetryReportingPolicy.sys.mjs"
     34  ).Policy;
     35  reportingPolicy.setShowInfobarTimeout = set;
     36  reportingPolicy.clearShowInfobarTimeout = clear;
     37 }
     38 
     39 async function sendSessionRestoredNotification() {
     40  let reportingPolicy = ChromeUtils.importESModule(
     41    "resource://gre/modules/TelemetryReportingPolicy.sys.mjs"
     42  ).Policy;
     43 
     44  await reportingPolicy.fakeSessionRestoreNotification();
     45 }
     46 
     47 /**
     48 * Wait for a tick.
     49 */
     50 function promiseNextTick() {
     51  return new Promise(resolve => executeSoon(resolve));
     52 }
     53 
     54 /**
     55 * Wait for a notification to be shown in a notification box.
     56 *
     57 * @param {object} aNotificationBox The notification box.
     58 * @return {Promise} Resolved when the notification is displayed.
     59 */
     60 function promiseWaitForAlertActive(aNotificationBox) {
     61  let deferred = Promise.withResolvers();
     62  aNotificationBox.stack.addEventListener(
     63    "AlertActive",
     64    function () {
     65      deferred.resolve();
     66    },
     67    { once: true }
     68  );
     69  return deferred.promise;
     70 }
     71 
     72 /**
     73 * Wait for a notification to be closed.
     74 *
     75 * @param {object} aNotification The notification.
     76 * @return {Promise} Resolved when the notification is closed.
     77 */
     78 function promiseWaitForNotificationClose(aNotification) {
     79  let deferred = Promise.withResolvers();
     80  waitForNotificationClose(aNotification, deferred.resolve);
     81  return deferred.promise;
     82 }
     83 
     84 async function triggerInfoBar(expectedTimeoutMs) {
     85  let showInfobarCallback = null;
     86  let timeoutMs = null;
     87  fakeShowPolicyTimeout(
     88    (callback, timeout) => {
     89      showInfobarCallback = callback;
     90      timeoutMs = timeout;
     91    },
     92    () => {}
     93  );
     94  await sendSessionRestoredNotification();
     95  Assert.ok(!!showInfobarCallback, "Must have a timer callback.");
     96  if (expectedTimeoutMs !== undefined) {
     97    Assert.equal(timeoutMs, expectedTimeoutMs, "Timeout should match");
     98  }
     99  showInfobarCallback();
    100 }
    101 
    102 add_setup(async function () {
    103  const isFirstRun = Preferences.get(PREF_FIRST_RUN, true);
    104  const bypassNotification = Preferences.get(PREF_BYPASS_NOTIFICATION, true);
    105  const currentPolicyVersion = Preferences.get(PREF_CURRENT_POLICY_VERSION, 1);
    106 
    107  // Register a cleanup function to reset our preferences.
    108  registerCleanupFunction(() => {
    109    Preferences.set(PREF_FIRST_RUN, isFirstRun);
    110    Preferences.set(PREF_BYPASS_NOTIFICATION, bypassNotification);
    111    Preferences.set(PREF_CURRENT_POLICY_VERSION, currentPolicyVersion);
    112    Preferences.reset(PREF_TELEMETRY_LOG_LEVEL);
    113    Preferences.reset(PREF_ACCEPTED_POLICY_VERSION);
    114    Preferences.reset(PREF_ACCEPTED_POLICY_DATE);
    115    Preferences.reset(PREF_TOS_ENABLED);
    116    Preferences.reset("browser.policies.alternatePath");
    117    return closeAllNotifications();
    118  });
    119 
    120  // Don't skip the infobar visualisation.
    121  Preferences.set(PREF_BYPASS_NOTIFICATION, false);
    122  // Set the current policy version.
    123  Preferences.set(PREF_CURRENT_POLICY_VERSION, TEST_POLICY_VERSION);
    124  // Ensure this isn't the first run, because then we open the first run page.
    125  Preferences.set(PREF_FIRST_RUN, false);
    126  TelemetryReportingPolicy.testUpdateFirstRun();
    127  // Do not enable the TOS modal
    128  Preferences.set(PREF_TOS_ENABLED, false);
    129 });
    130 
    131 function clearAcceptedPolicy() {
    132  // Reset the accepted policy.
    133  Preferences.reset(PREF_ACCEPTED_POLICY_VERSION);
    134  Preferences.reset(PREF_ACCEPTED_POLICY_DATE);
    135 }
    136 
    137 function assertCoherentInitialState() {
    138  // Make sure that we have a coherent initial state.
    139  Assert.equal(
    140    Preferences.get(PREF_ACCEPTED_POLICY_VERSION, 0),
    141    0,
    142    "No version should be set on init."
    143  );
    144  Assert.equal(
    145    Preferences.get(PREF_ACCEPTED_POLICY_DATE, 0),
    146    0,
    147    "No date should be set on init."
    148  );
    149  Assert.ok(
    150    !TelemetryReportingPolicy.testIsUserNotifiedOfDataReportingPolicy(),
    151    "User not notified about datareporting policy."
    152  );
    153 }
    154 
    155 add_task(async function test_single_window() {
    156  TelemetryReportingPolicy.reset();
    157  clearAcceptedPolicy();
    158 
    159  // Close all the notifications, then try to trigger the data choices infobar.
    160  await closeAllNotifications();
    161 
    162  assertCoherentInitialState();
    163 
    164  let alertShownPromise = promiseWaitForAlertActive(gNotificationBox);
    165  Assert.ok(
    166    !TelemetryReportingPolicy.canUpload(),
    167    "User should not be allowed to upload."
    168  );
    169 
    170  // Wait for the infobar to be displayed.
    171  await triggerInfoBar(10 * 1000);
    172 
    173  await alertShownPromise;
    174  await promiseNextTick();
    175 
    176  Assert.equal(
    177    gNotificationBox.allNotifications.length,
    178    1,
    179    "Notification Displayed."
    180  );
    181  Assert.ok(
    182    TelemetryReportingPolicy.canUpload(),
    183    "User should be allowed to upload now."
    184  );
    185 
    186  // Close the infobar without opening the prefs UI to avoid side effects that
    187  // change prefs.
    188  let notifications = gNotificationBox.allNotifications;
    189  Assert.equal(notifications.length, 1, "One notification present to close");
    190  let notification = notifications[0];
    191  let promiseClosed = promiseWaitForNotificationClose(notification);
    192  notification.close();
    193  await promiseClosed;
    194 
    195  Assert.equal(
    196    gNotificationBox.allNotifications.length,
    197    0,
    198    "No notifications remain."
    199  );
    200 
    201  // Check that we are still clear to upload and that the policy data is saved.
    202  Assert.ok(TelemetryReportingPolicy.canUpload());
    203  Assert.equal(
    204    TelemetryReportingPolicy.testIsUserNotifiedOfDataReportingPolicy(),
    205    true,
    206    "User notified about datareporting policy."
    207  );
    208  Assert.equal(
    209    Preferences.get(PREF_ACCEPTED_POLICY_VERSION, 0),
    210    TEST_POLICY_VERSION,
    211    "Version pref set."
    212  );
    213  Assert.greater(
    214    parseInt(Preferences.get(PREF_ACCEPTED_POLICY_DATE, null), 10),
    215    -1,
    216    "Date pref set."
    217  );
    218 });
    219 
    220 /* See bug 1571932
    221 add_task(async function test_multiple_windows() {
    222  clearAcceptedPolicy();
    223 
    224  // Close all the notifications, then try to trigger the data choices infobar.
    225  await closeAllNotifications();
    226 
    227  // Ensure we see the notification on all windows and that action on one window
    228  // results in dismiss on every window.
    229  let otherWindow = await BrowserTestUtils.openNewBrowserWindow();
    230 
    231  Assert.ok(
    232    otherWindow.gNotificationBox,
    233    "2nd window has a global notification box."
    234  );
    235 
    236  assertCoherentInitialState();
    237 
    238  let showAlertPromises = [
    239    promiseWaitForAlertActive(gNotificationBox),
    240    promiseWaitForAlertActive(otherWindow.gNotificationBox),
    241  ];
    242 
    243  Assert.ok(
    244    !TelemetryReportingPolicy.canUpload(),
    245    "User should not be allowed to upload."
    246  );
    247 
    248  // Wait for the infobars.
    249  await triggerInfoBar(10 * 1000);
    250  await Promise.all(showAlertPromises);
    251 
    252  // Both notification were displayed. Close one and check that both gets closed.
    253  let closeAlertPromises = [
    254    promiseWaitForNotificationClose(gNotificationBox.currentNotification),
    255    promiseWaitForNotificationClose(
    256      otherWindow.gNotificationBox.currentNotification
    257    ),
    258  ];
    259  gNotificationBox.currentNotification.close();
    260  await Promise.all(closeAlertPromises);
    261 
    262  // Close the second window we opened.
    263  await BrowserTestUtils.closeWindow(otherWindow);
    264 
    265  // Check that we are clear to upload and that the policy data us saved.
    266  Assert.ok(
    267    TelemetryReportingPolicy.canUpload(),
    268    "User should be allowed to upload now."
    269  );
    270  Assert.equal(
    271    TelemetryReportingPolicy.testIsUserNotifiedOfDataReportingPolicy(),
    272    true,
    273    "User notified about datareporting policy."
    274  );
    275  Assert.equal(
    276    Preferences.get(PREF_ACCEPTED_POLICY_VERSION, 0),
    277    TEST_POLICY_VERSION,
    278    "Version pref set."
    279  );
    280  Assert.greater(
    281    parseInt(Preferences.get(PREF_ACCEPTED_POLICY_DATE, null), 10),
    282    -1,
    283    "Date pref set."
    284  );
    285 });*/