summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/general/browser_datachoices_notification.js
blob: eb2ec5ee376970f8d1bd2179ecb357d68c84fcec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

var { Preferences } = ChromeUtils.importESModule(
  "resource://gre/modules/Preferences.sys.mjs"
);
var { TelemetryReportingPolicy } = ChromeUtils.importESModule(
  "resource://gre/modules/TelemetryReportingPolicy.sys.mjs"
);

const PREF_BRANCH = "datareporting.policy.";
const PREF_FIRST_RUN = "toolkit.telemetry.reportingpolicy.firstRun";
const PREF_BYPASS_NOTIFICATION =
  PREF_BRANCH + "dataSubmissionPolicyBypassNotification";
const PREF_CURRENT_POLICY_VERSION = PREF_BRANCH + "currentPolicyVersion";
const PREF_ACCEPTED_POLICY_VERSION =
  PREF_BRANCH + "dataSubmissionPolicyAcceptedVersion";
const PREF_ACCEPTED_POLICY_DATE =
  PREF_BRANCH + "dataSubmissionPolicyNotifiedTime";

const PREF_TELEMETRY_LOG_LEVEL = "toolkit.telemetry.log.level";

const TEST_POLICY_VERSION = 37;

function fakeShowPolicyTimeout(set, clear) {
  let reportingPolicy = ChromeUtils.importESModule(
    "resource://gre/modules/TelemetryReportingPolicy.sys.mjs"
  ).Policy;
  reportingPolicy.setShowInfobarTimeout = set;
  reportingPolicy.clearShowInfobarTimeout = clear;
}

function sendSessionRestoredNotification() {
  let reportingPolicy = ChromeUtils.importESModule(
    "resource://gre/modules/TelemetryReportingPolicy.sys.mjs"
  ).Policy;

  reportingPolicy.fakeSessionRestoreNotification();
}

/**
 * Wait for a tick.
 */
function promiseNextTick() {
  return new Promise(resolve => executeSoon(resolve));
}

/**
 * Wait for a notification to be shown in a notification box.
 * @param {Object} aNotificationBox The notification box.
 * @return {Promise} Resolved when the notification is displayed.
 */
function promiseWaitForAlertActive(aNotificationBox) {
  let deferred = PromiseUtils.defer();
  aNotificationBox.stack.addEventListener(
    "AlertActive",
    function () {
      deferred.resolve();
    },
    { once: true }
  );
  return deferred.promise;
}

/**
 * Wait for a notification to be closed.
 * @param {Object} aNotification The notification.
 * @return {Promise} Resolved when the notification is closed.
 */
function promiseWaitForNotificationClose(aNotification) {
  let deferred = PromiseUtils.defer();
  waitForNotificationClose(aNotification, deferred.resolve);
  return deferred.promise;
}

function triggerInfoBar(expectedTimeoutMs) {
  let showInfobarCallback = null;
  let timeoutMs = null;
  fakeShowPolicyTimeout(
    (callback, timeout) => {
      showInfobarCallback = callback;
      timeoutMs = timeout;
    },
    () => {}
  );
  sendSessionRestoredNotification();
  Assert.ok(!!showInfobarCallback, "Must have a timer callback.");
  if (expectedTimeoutMs !== undefined) {
    Assert.equal(timeoutMs, expectedTimeoutMs, "Timeout should match");
  }
  showInfobarCallback();
}

var checkInfobarButton = async function (aNotification) {
  // Check that the button on the data choices infobar does the right thing.
  let buttons = aNotification.buttonContainer.getElementsByTagName("button");
  Assert.equal(
    buttons.length,
    1,
    "There is 1 button in the data reporting notification."
  );
  let button = buttons[0];

  // Click on the button.
  button.click();

  // Wait for the preferences panel to open.
  await promiseNextTick();
};

add_setup(async function () {
  const isFirstRun = Preferences.get(PREF_FIRST_RUN, true);
  const bypassNotification = Preferences.get(PREF_BYPASS_NOTIFICATION, true);
  const currentPolicyVersion = Preferences.get(PREF_CURRENT_POLICY_VERSION, 1);

  // Register a cleanup function to reset our preferences.
  registerCleanupFunction(() => {
    Preferences.set(PREF_FIRST_RUN, isFirstRun);
    Preferences.set(PREF_BYPASS_NOTIFICATION, bypassNotification);
    Preferences.set(PREF_CURRENT_POLICY_VERSION, currentPolicyVersion);
    Preferences.reset(PREF_TELEMETRY_LOG_LEVEL);

    return closeAllNotifications();
  });

  // Don't skip the infobar visualisation.
  Preferences.set(PREF_BYPASS_NOTIFICATION, false);
  // Set the current policy version.
  Preferences.set(PREF_CURRENT_POLICY_VERSION, TEST_POLICY_VERSION);
  // Ensure this isn't the first run, because then we open the first run page.
  Preferences.set(PREF_FIRST_RUN, false);
  TelemetryReportingPolicy.testUpdateFirstRun();
});

function clearAcceptedPolicy() {
  // Reset the accepted policy.
  Preferences.reset(PREF_ACCEPTED_POLICY_VERSION);
  Preferences.reset(PREF_ACCEPTED_POLICY_DATE);
}

function assertCoherentInitialState() {
  // Make sure that we have a coherent initial state.
  Assert.equal(
    Preferences.get(PREF_ACCEPTED_POLICY_VERSION, 0),
    0,
    "No version should be set on init."
  );
  Assert.equal(
    Preferences.get(PREF_ACCEPTED_POLICY_DATE, 0),
    0,
    "No date should be set on init."
  );
  Assert.ok(
    !TelemetryReportingPolicy.testIsUserNotified(),
    "User not notified about datareporting policy."
  );
}

add_task(async function test_single_window() {
  clearAcceptedPolicy();

  // Close all the notifications, then try to trigger the data choices infobar.
  await closeAllNotifications();

  assertCoherentInitialState();

  let alertShownPromise = promiseWaitForAlertActive(gNotificationBox);
  Assert.ok(
    !TelemetryReportingPolicy.canUpload(),
    "User should not be allowed to upload."
  );

  // Wait for the infobar to be displayed.
  triggerInfoBar(10 * 1000);
  await alertShownPromise;

  Assert.equal(
    gNotificationBox.allNotifications.length,
    1,
    "Notification Displayed."
  );
  Assert.ok(
    TelemetryReportingPolicy.canUpload(),
    "User should be allowed to upload now."
  );

  await promiseNextTick();
  let promiseClosed = promiseWaitForNotificationClose(
    gNotificationBox.currentNotification
  );
  await checkInfobarButton(gNotificationBox.currentNotification);
  await promiseClosed;

  Assert.equal(
    gNotificationBox.allNotifications.length,
    0,
    "No notifications remain."
  );

  // Check that we are still clear to upload and that the policy data is saved.
  Assert.ok(TelemetryReportingPolicy.canUpload());
  Assert.equal(
    TelemetryReportingPolicy.testIsUserNotified(),
    true,
    "User notified about datareporting policy."
  );
  Assert.equal(
    Preferences.get(PREF_ACCEPTED_POLICY_VERSION, 0),
    TEST_POLICY_VERSION,
    "Version pref set."
  );
  Assert.greater(
    parseInt(Preferences.get(PREF_ACCEPTED_POLICY_DATE, null), 10),
    -1,
    "Date pref set."
  );
});

/* See bug 1571932
add_task(async function test_multiple_windows() {
  clearAcceptedPolicy();

  // Close all the notifications, then try to trigger the data choices infobar.
  await closeAllNotifications();

  // Ensure we see the notification on all windows and that action on one window
  // results in dismiss on every window.
  let otherWindow = await BrowserTestUtils.openNewBrowserWindow();

  Assert.ok(
    otherWindow.gNotificationBox,
    "2nd window has a global notification box."
  );

  assertCoherentInitialState();

  let showAlertPromises = [
    promiseWaitForAlertActive(gNotificationBox),
    promiseWaitForAlertActive(otherWindow.gNotificationBox),
  ];

  Assert.ok(
    !TelemetryReportingPolicy.canUpload(),
    "User should not be allowed to upload."
  );

  // Wait for the infobars.
  triggerInfoBar(10 * 1000);
  await Promise.all(showAlertPromises);

  // Both notification were displayed. Close one and check that both gets closed.
  let closeAlertPromises = [
    promiseWaitForNotificationClose(gNotificationBox.currentNotification),
    promiseWaitForNotificationClose(
      otherWindow.gNotificationBox.currentNotification
    ),
  ];
  gNotificationBox.currentNotification.close();
  await Promise.all(closeAlertPromises);

  // Close the second window we opened.
  await BrowserTestUtils.closeWindow(otherWindow);

  // Check that we are clear to upload and that the policy data us saved.
  Assert.ok(
    TelemetryReportingPolicy.canUpload(),
    "User should be allowed to upload now."
  );
  Assert.equal(
    TelemetryReportingPolicy.testIsUserNotified(),
    true,
    "User notified about datareporting policy."
  );
  Assert.equal(
    Preferences.get(PREF_ACCEPTED_POLICY_VERSION, 0),
    TEST_POLICY_VERSION,
    "Version pref set."
  );
  Assert.greater(
    parseInt(Preferences.get(PREF_ACCEPTED_POLICY_DATE, null), 10),
    -1,
    "Date pref set."
  );
});*/