Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
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/. */
5 function sendNotifyRequest(name) {
6 let ns = {};
7 Components.utils.import("resource://gre/modules/services/datareporting/policy.jsm", ns);
8 Components.utils.import("resource://gre/modules/Preferences.jsm", ns);
10 let service = Components.classes["@mozilla.org/datareporting/service;1"]
11 .getService(Components.interfaces.nsISupports)
12 .wrappedJSObject;
13 ok(service.healthReporter, "Health Reporter instance is available.");
15 let policyPrefs = new ns.Preferences("testing." + name + ".");
16 ok(service._prefs, "Health Reporter prefs are available.");
17 let hrPrefs = service._prefs;
19 let policy = new ns.DataReportingPolicy(policyPrefs, hrPrefs, service);
20 policy.firstRunDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
22 is(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED, "Policy is in unnotified state.");
24 service.healthReporter.onInit().then(function onInit() {
25 is(policy.ensureNotifyResponse(new Date()), false, "User has not responded to policy.");
26 });
28 return policy;
29 }
31 /**
32 * Wait for a <notification> to be closed then call the specified callback.
33 */
34 function waitForNotificationClose(notification, cb) {
35 let parent = notification.parentNode;
37 let observer = new MutationObserver(function onMutatations(mutations) {
38 for (let mutation of mutations) {
39 for (let i = 0; i < mutation.removedNodes.length; i++) {
40 let node = mutation.removedNodes.item(i);
42 if (node != notification) {
43 continue;
44 }
46 observer.disconnect();
47 cb();
48 }
49 }
50 });
52 observer.observe(parent, {childList: true});
53 }
55 let dumpAppender, rootLogger;
57 function test() {
58 waitForExplicitFinish();
60 let ns = {};
61 Components.utils.import("resource://gre/modules/Log.jsm", ns);
62 rootLogger = ns.Log.repository.rootLogger;
63 dumpAppender = new ns.Log.DumpAppender();
64 dumpAppender.level = ns.Log.Level.All;
65 rootLogger.addAppender(dumpAppender);
67 let notification = document.getElementById("global-notificationbox");
68 let policy;
70 notification.addEventListener("AlertActive", function active() {
71 notification.removeEventListener("AlertActive", active, true);
73 executeSoon(function afterNotification() {
74 is(policy.notifyState, policy.STATE_NOTIFY_WAIT, "Policy is waiting for user response.");
75 ok(!policy.dataSubmissionPolicyAccepted, "Data submission policy not yet accepted.");
77 waitForNotificationClose(notification.currentNotification, function onClose() {
78 is(policy.notifyState, policy.STATE_NOTIFY_COMPLETE, "Closing info bar completes user notification.");
79 ok(policy.dataSubmissionPolicyAccepted, "Data submission policy accepted.");
80 is(policy.dataSubmissionPolicyResponseType, "accepted-info-bar-dismissed",
81 "Reason for acceptance was info bar dismissal.");
82 is(notification.allNotifications.length, 0, "No notifications remain.");
83 test_multiple_windows();
84 });
85 notification.currentNotification.close();
86 });
87 }, true);
89 policy = sendNotifyRequest("single_window_notified");
90 }
92 function test_multiple_windows() {
93 // Ensure we see the notification on all windows and that action on one window
94 // results in dismiss on every window.
95 let window2 = OpenBrowserWindow();
96 whenDelayedStartupFinished(window2, function onWindow() {
97 let notification1 = document.getElementById("global-notificationbox");
98 let notification2 = window2.document.getElementById("global-notificationbox");
99 ok(notification2, "2nd window has a global notification box.");
101 let policy;
103 let displayCount = 0;
104 let prefPaneClosed = false;
105 let childWindowClosed = false;
107 function onAlertDisplayed() {
108 displayCount++;
110 if (displayCount != 2) {
111 return;
112 }
114 ok(true, "Data reporting info bar displayed on all open windows.");
116 // We register two independent observers and we need both to clean up
117 // properly. This handles gating for test completion.
118 function maybeFinish() {
119 if (!prefPaneClosed) {
120 dump("Not finishing test yet because pref pane isn't closed.\n");
121 return;
122 }
124 if (!childWindowClosed) {
125 dump("Not finishing test yet because child window isn't closed.\n");
126 return;
127 }
129 dump("Finishing multiple window test.\n");
130 rootLogger.removeAppender(dumpAppender);
131 delete dumpAppender;
132 delete rootLogger;
133 finish();
134 }
136 let closeCount = 0;
137 function onAlertClose() {
138 closeCount++;
140 if (closeCount != 2) {
141 return;
142 }
144 ok(true, "Closing info bar on one window closed them on all.");
146 is(policy.notifyState, policy.STATE_NOTIFY_COMPLETE,
147 "Closing info bar with multiple windows completes notification.");
148 ok(policy.dataSubmissionPolicyAccepted, "Data submission policy accepted.");
149 is(policy.dataSubmissionPolicyResponseType, "accepted-info-bar-button-pressed",
150 "Policy records reason for acceptance was button press.");
151 is(notification1.allNotifications.length, 0, "No notifications remain on main window.");
152 is(notification2.allNotifications.length, 0, "No notifications remain on 2nd window.");
154 window2.close();
155 childWindowClosed = true;
156 maybeFinish();
157 }
159 waitForNotificationClose(notification1.currentNotification, onAlertClose);
160 waitForNotificationClose(notification2.currentNotification, onAlertClose);
162 // While we're here, we dual purpose this test to check that pressing the
163 // button does the right thing.
164 let buttons = notification2.currentNotification.getElementsByTagName("button");
165 is(buttons.length, 1, "There is 1 button in the data reporting notification.");
166 let button = buttons[0];
168 // Automatically close preferences window when it is opened as part of
169 // button press.
170 Services.obs.addObserver(function observer(prefWin, topic, data) {
171 Services.obs.removeObserver(observer, "advanced-pane-loaded");
173 ok(true, "Pref pane opened on info bar button press.");
174 executeSoon(function soon() {
175 dump("Closing pref pane.\n");
176 prefWin.close();
177 prefPaneClosed = true;
178 maybeFinish();
179 });
180 }, "advanced-pane-loaded", false);
182 button.click();
183 }
185 notification1.addEventListener("AlertActive", function active1() {
186 notification1.removeEventListener("AlertActive", active1, true);
187 executeSoon(onAlertDisplayed);
188 }, true);
190 notification2.addEventListener("AlertActive", function active2() {
191 notification2.removeEventListener("AlertActive", active2, true);
192 executeSoon(onAlertDisplayed);
193 }, true);
195 policy = sendNotifyRequest("multiple_window_behavior");
196 });
197 }