1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/base/content/test/general/browser_datareporting_notification.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,198 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +function sendNotifyRequest(name) { 1.9 + let ns = {}; 1.10 + Components.utils.import("resource://gre/modules/services/datareporting/policy.jsm", ns); 1.11 + Components.utils.import("resource://gre/modules/Preferences.jsm", ns); 1.12 + 1.13 + let service = Components.classes["@mozilla.org/datareporting/service;1"] 1.14 + .getService(Components.interfaces.nsISupports) 1.15 + .wrappedJSObject; 1.16 + ok(service.healthReporter, "Health Reporter instance is available."); 1.17 + 1.18 + let policyPrefs = new ns.Preferences("testing." + name + "."); 1.19 + ok(service._prefs, "Health Reporter prefs are available."); 1.20 + let hrPrefs = service._prefs; 1.21 + 1.22 + let policy = new ns.DataReportingPolicy(policyPrefs, hrPrefs, service); 1.23 + policy.firstRunDate = new Date(Date.now() - 24 * 60 * 60 * 1000); 1.24 + 1.25 + is(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED, "Policy is in unnotified state."); 1.26 + 1.27 + service.healthReporter.onInit().then(function onInit() { 1.28 + is(policy.ensureNotifyResponse(new Date()), false, "User has not responded to policy."); 1.29 + }); 1.30 + 1.31 + return policy; 1.32 +} 1.33 + 1.34 +/** 1.35 + * Wait for a <notification> to be closed then call the specified callback. 1.36 + */ 1.37 +function waitForNotificationClose(notification, cb) { 1.38 + let parent = notification.parentNode; 1.39 + 1.40 + let observer = new MutationObserver(function onMutatations(mutations) { 1.41 + for (let mutation of mutations) { 1.42 + for (let i = 0; i < mutation.removedNodes.length; i++) { 1.43 + let node = mutation.removedNodes.item(i); 1.44 + 1.45 + if (node != notification) { 1.46 + continue; 1.47 + } 1.48 + 1.49 + observer.disconnect(); 1.50 + cb(); 1.51 + } 1.52 + } 1.53 + }); 1.54 + 1.55 + observer.observe(parent, {childList: true}); 1.56 +} 1.57 + 1.58 +let dumpAppender, rootLogger; 1.59 + 1.60 +function test() { 1.61 + waitForExplicitFinish(); 1.62 + 1.63 + let ns = {}; 1.64 + Components.utils.import("resource://gre/modules/Log.jsm", ns); 1.65 + rootLogger = ns.Log.repository.rootLogger; 1.66 + dumpAppender = new ns.Log.DumpAppender(); 1.67 + dumpAppender.level = ns.Log.Level.All; 1.68 + rootLogger.addAppender(dumpAppender); 1.69 + 1.70 + let notification = document.getElementById("global-notificationbox"); 1.71 + let policy; 1.72 + 1.73 + notification.addEventListener("AlertActive", function active() { 1.74 + notification.removeEventListener("AlertActive", active, true); 1.75 + 1.76 + executeSoon(function afterNotification() { 1.77 + is(policy.notifyState, policy.STATE_NOTIFY_WAIT, "Policy is waiting for user response."); 1.78 + ok(!policy.dataSubmissionPolicyAccepted, "Data submission policy not yet accepted."); 1.79 + 1.80 + waitForNotificationClose(notification.currentNotification, function onClose() { 1.81 + is(policy.notifyState, policy.STATE_NOTIFY_COMPLETE, "Closing info bar completes user notification."); 1.82 + ok(policy.dataSubmissionPolicyAccepted, "Data submission policy accepted."); 1.83 + is(policy.dataSubmissionPolicyResponseType, "accepted-info-bar-dismissed", 1.84 + "Reason for acceptance was info bar dismissal."); 1.85 + is(notification.allNotifications.length, 0, "No notifications remain."); 1.86 + test_multiple_windows(); 1.87 + }); 1.88 + notification.currentNotification.close(); 1.89 + }); 1.90 + }, true); 1.91 + 1.92 + policy = sendNotifyRequest("single_window_notified"); 1.93 +} 1.94 + 1.95 +function test_multiple_windows() { 1.96 + // Ensure we see the notification on all windows and that action on one window 1.97 + // results in dismiss on every window. 1.98 + let window2 = OpenBrowserWindow(); 1.99 + whenDelayedStartupFinished(window2, function onWindow() { 1.100 + let notification1 = document.getElementById("global-notificationbox"); 1.101 + let notification2 = window2.document.getElementById("global-notificationbox"); 1.102 + ok(notification2, "2nd window has a global notification box."); 1.103 + 1.104 + let policy; 1.105 + 1.106 + let displayCount = 0; 1.107 + let prefPaneClosed = false; 1.108 + let childWindowClosed = false; 1.109 + 1.110 + function onAlertDisplayed() { 1.111 + displayCount++; 1.112 + 1.113 + if (displayCount != 2) { 1.114 + return; 1.115 + } 1.116 + 1.117 + ok(true, "Data reporting info bar displayed on all open windows."); 1.118 + 1.119 + // We register two independent observers and we need both to clean up 1.120 + // properly. This handles gating for test completion. 1.121 + function maybeFinish() { 1.122 + if (!prefPaneClosed) { 1.123 + dump("Not finishing test yet because pref pane isn't closed.\n"); 1.124 + return; 1.125 + } 1.126 + 1.127 + if (!childWindowClosed) { 1.128 + dump("Not finishing test yet because child window isn't closed.\n"); 1.129 + return; 1.130 + } 1.131 + 1.132 + dump("Finishing multiple window test.\n"); 1.133 + rootLogger.removeAppender(dumpAppender); 1.134 + delete dumpAppender; 1.135 + delete rootLogger; 1.136 + finish(); 1.137 + } 1.138 + 1.139 + let closeCount = 0; 1.140 + function onAlertClose() { 1.141 + closeCount++; 1.142 + 1.143 + if (closeCount != 2) { 1.144 + return; 1.145 + } 1.146 + 1.147 + ok(true, "Closing info bar on one window closed them on all."); 1.148 + 1.149 + is(policy.notifyState, policy.STATE_NOTIFY_COMPLETE, 1.150 + "Closing info bar with multiple windows completes notification."); 1.151 + ok(policy.dataSubmissionPolicyAccepted, "Data submission policy accepted."); 1.152 + is(policy.dataSubmissionPolicyResponseType, "accepted-info-bar-button-pressed", 1.153 + "Policy records reason for acceptance was button press."); 1.154 + is(notification1.allNotifications.length, 0, "No notifications remain on main window."); 1.155 + is(notification2.allNotifications.length, 0, "No notifications remain on 2nd window."); 1.156 + 1.157 + window2.close(); 1.158 + childWindowClosed = true; 1.159 + maybeFinish(); 1.160 + } 1.161 + 1.162 + waitForNotificationClose(notification1.currentNotification, onAlertClose); 1.163 + waitForNotificationClose(notification2.currentNotification, onAlertClose); 1.164 + 1.165 + // While we're here, we dual purpose this test to check that pressing the 1.166 + // button does the right thing. 1.167 + let buttons = notification2.currentNotification.getElementsByTagName("button"); 1.168 + is(buttons.length, 1, "There is 1 button in the data reporting notification."); 1.169 + let button = buttons[0]; 1.170 + 1.171 + // Automatically close preferences window when it is opened as part of 1.172 + // button press. 1.173 + Services.obs.addObserver(function observer(prefWin, topic, data) { 1.174 + Services.obs.removeObserver(observer, "advanced-pane-loaded"); 1.175 + 1.176 + ok(true, "Pref pane opened on info bar button press."); 1.177 + executeSoon(function soon() { 1.178 + dump("Closing pref pane.\n"); 1.179 + prefWin.close(); 1.180 + prefPaneClosed = true; 1.181 + maybeFinish(); 1.182 + }); 1.183 + }, "advanced-pane-loaded", false); 1.184 + 1.185 + button.click(); 1.186 + } 1.187 + 1.188 + notification1.addEventListener("AlertActive", function active1() { 1.189 + notification1.removeEventListener("AlertActive", active1, true); 1.190 + executeSoon(onAlertDisplayed); 1.191 + }, true); 1.192 + 1.193 + notification2.addEventListener("AlertActive", function active2() { 1.194 + notification2.removeEventListener("AlertActive", active2, true); 1.195 + executeSoon(onAlertDisplayed); 1.196 + }, true); 1.197 + 1.198 + policy = sendNotifyRequest("multiple_window_behavior"); 1.199 + }); 1.200 +} 1.201 +