summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/general/browser_datachoices_notification.js
blob: 360728b4c536ccd38a1a05e1c9598d7ff56355e5 (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
/* 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";

// Pass an empty scope object to the import to prevent "leaked window property"
// errors in tests.
var Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
var TelemetryReportingPolicy =
  Cu.import("resource://gre/modules/TelemetryReportingPolicy.jsm", {}).TelemetryReportingPolicy;

const PREF_BRANCH = "datareporting.policy.";
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 TEST_POLICY_VERSION = 37;

function fakeShowPolicyTimeout(set, clear) {
  let reportingPolicy =
    Cu.import("resource://gre/modules/TelemetryReportingPolicy.jsm", {}).Policy;
  reportingPolicy.setShowInfobarTimeout = set;
  reportingPolicy.clearShowInfobarTimeout = clear;
}

function sendSessionRestoredNotification() {
  let reportingPolicyImpl =
    Cu.import("resource://gre/modules/TelemetryReportingPolicy.jsm", {}).TelemetryReportingPolicyImpl;
  reportingPolicyImpl.observe(null, "sessionstore-windows-restored", null);
}

/**
 * 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.addEventListener("AlertActive", function onActive() {
    aNotificationBox.removeEventListener("AlertActive", onActive, true);
    deferred.resolve();
  });
  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 = Task.async(function* (aNotification) {
  // Check that the button on the data choices infobar does the right thing.
  let buttons = aNotification.getElementsByTagName("button");
  Assert.equal(buttons.length, 1, "There is 1 button in the data reporting notification.");
  let button = buttons[0];

  // Add an observer to ensure the "advanced" pane opened (but don't bother
  // closing it - we close the entire window when done.)
  let paneLoadedPromise = promiseTopicObserved("advanced-pane-loaded");

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

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

add_task(function* setup() {
  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_BYPASS_NOTIFICATION, bypassNotification);
    Preferences.set(PREF_CURRENT_POLICY_VERSION, currentPolicyVersion);

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

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

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

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

  let notificationBox = document.getElementById("global-notificationbox");

  // 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.");

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

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

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

  yield promiseNextTick();
  let promiseClosed = promiseWaitForNotificationClose(notificationBox.currentNotification);
  yield checkInfobarButton(notificationBox.currentNotification);
  yield promiseClosed;

  Assert.equal(notificationBox.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.");
});

add_task(function* test_multiple_windows() {
  clearAcceptedPolicy();

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

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

  // Get the notification box for both windows.
  let notificationBoxes = [
    document.getElementById("global-notificationbox"),
    otherWindow.document.getElementById("global-notificationbox")
  ];

  Assert.ok(notificationBoxes[1], "2nd window has a global notification box.");

  // 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.");

  let showAlertPromises = [
    promiseWaitForAlertActive(notificationBoxes[0]),
    promiseWaitForAlertActive(notificationBoxes[1])
  ];

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

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

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

  // Close the second window we opened.
  yield 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.");
});