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 });*/