diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 8d94b080cdcb..975f71033e63 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1825,12 +1825,6 @@ pref("extensions.screenshots.disabled", false); // disable uploading to the server. pref("extensions.screenshots.upload-disabled", false); -// DoH Rollout: the earliest date of profile creation for which we don't need -// to show the doorhanger. This is when the version of the privacy statement -// that includes DoH went live - Oct 31, 2019. This has to be a string because -// the number is outside the signed 32-bit integer range. -pref("doh-rollout.profileCreationThreshold", "1572476400000"); - // URL for Learn More link for browser error logging in preferences pref("browser.chrome.errorReporter.infoURL", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/nightly-error-collection"); diff --git a/browser/extensions/doh-rollout/background.js b/browser/extensions/doh-rollout/background.js index eb0659299e26..ee4ea1693839 100644 --- a/browser/extensions/doh-rollout/background.js +++ b/browser/extensions/doh-rollout/background.js @@ -189,10 +189,16 @@ const stateManager = { return !doorhangerShown; }, - async showDoorhanger() { - rollout.addDoorhangerListeners(); + async showDoorHangerAndEnableDoH() { + browser.experiments.doorhanger.onDoorhangerAccept.addListener( + rollout.doorhangerAcceptListener + ); - let doorhangerShown = await browser.experiments.doorhanger.show({ + browser.experiments.doorhanger.onDoorhangerDecline.addListener( + rollout.doorhangerDeclineListener + ); + + await browser.experiments.doorhanger.show({ name: browser.i18n.getMessage("doorhangerName"), text: "<> " + browser.i18n.getMessage("doorhangerBody"), okLabel: browser.i18n.getMessage("doorhangerButtonOk"), @@ -203,15 +209,9 @@ const stateManager = { ), }); - if (!doorhangerShown) { - // The profile was created after the go-live date of the privacy statement - // that included DoH. Treat it as accepted. - log("Profile is new, doorhanger not shown."); - await stateManager.setState("UIOk"); - await stateManager.rememberDoorhangerDecision("NewProfile"); - await stateManager.rememberDoorhangerShown(); - rollout.removeDoorhangerListeners(); - } + // By default, enable DoH when showing the doorhanger, + // if heuristics returned no reason to not run. + await stateManager.setState("enabled"); }, }; @@ -227,32 +227,11 @@ const rollout = { return this._isTesting; }, - addDoorhangerListeners() { - browser.experiments.doorhanger.onDoorhangerAccept.addListener( - rollout.doorhangerAcceptListener - ); - - browser.experiments.doorhanger.onDoorhangerDecline.addListener( - rollout.doorhangerDeclineListener - ); - }, - - removeDoorhangerListeners() { - browser.experiments.doorhanger.onDoorhangerAccept.removeListener( - rollout.doorhangerAcceptListener - ); - - browser.experiments.doorhanger.onDoorhangerDecline.removeListener( - rollout.doorhangerDeclineListener - ); - }, - async doorhangerAcceptListener(tabId) { log("Doorhanger accepted on tab", tabId); await stateManager.setState("UIOk"); await stateManager.rememberDoorhangerDecision("UIOk"); await stateManager.rememberDoorhangerShown(); - rollout.removeDoorhangerListeners(); }, async doorhangerDeclineListener(tabId) { @@ -264,23 +243,16 @@ const rollout = { browser.experiments.heuristics.sendHeuristicsPing("disable_doh", results); await stateManager.rememberDisableHeuristics(); await stateManager.rememberDoorhangerShown(); - rollout.removeDoorhangerListeners(); }, async heuristics(evaluateReason) { - let shouldRunHeuristics = await stateManager.shouldRunHeuristics(); - - if (!shouldRunHeuristics) { - return; - } - // Run heuristics defined in heuristics.js and experiments/heuristics/api.js let results; if (await rollout.isTesting()) { results = await browser.experiments.preferences.getCharPref( MOCK_HEURISTICS_PREF, - `{ "test": "disable_doh" }` + "disable_doh" ); results = JSON.parse(results); } else { @@ -298,14 +270,7 @@ const rollout = { results.evaluateReason = evaluateReason; browser.experiments.heuristics.sendHeuristicsPing(decision, results); - if (decision === "disable_doh") { - await stateManager.setState("disabled"); - } else { - await stateManager.setState("enabled"); - if (await stateManager.shouldShowDoorhanger()) { - await stateManager.showDoorhanger(); - } - } + return decision; }, async getSetting(name, defaultValue) { @@ -507,67 +472,81 @@ const rollout = { await this.enterprisePolicyCheck("startup", results); } - if (!(await stateManager.shouldRunHeuristics())) { - return; - } - - let networkStatus = (await browser.networkStatus.getLinkInfo()).status; - let captiveState = "unknown"; - try { - captiveState = await browser.captivePortal.getState(); - } catch (e) { - // Captive Portal Service is disabled. - } - - if (networkStatus == "up" && captiveState != "locked_portal") { - await rollout.heuristics("startup"); + if (await stateManager.shouldRunHeuristics()) { + await this.runStartupHeuristics(); } // Listen for network change events to run heuristics again - browser.networkStatus.onConnectionChanged.addListener( - rollout.onConnectionChanged - ); + browser.networkStatus.onConnectionChanged.addListener(async () => { + log("onConnectionChanged"); + + let linkInfo = await browser.networkStatus.getLinkInfo(); + if (linkInfo.status !== "up") { + log("Link down."); + if (rollout.networkSettledTimeout) { + log("Canceling queued heuristics run."); + clearTimeout(rollout.networkSettledTimeout); + rollout.networkSettledTimeout = null; + } + return; + } + + log("Queing a heuristics run in 60s, will cancel if network fluctuates."); + let gracePeriod = (await rollout.isTesting()) ? 0 : 60000; + rollout.networkSettledTimeout = setTimeout(async () => { + log("No network fluctuation for 60 seconds, running heuristics."); + // Only run the heuristics if user hasn't explicitly enabled/disabled DoH + let shouldRunHeuristics = await stateManager.shouldRunHeuristics(); + let shouldShowDoorhanger = await stateManager.shouldShowDoorhanger(); + + if (!shouldRunHeuristics) { + return; + } + + const netChangeDecision = await rollout.heuristics("netChange"); + + if (netChangeDecision === "disable_doh") { + await stateManager.setState("disabled"); + } else if (shouldShowDoorhanger) { + await stateManager.showDoorHangerAndEnableDoH(); + } else { + await stateManager.setState("enabled"); + } + }, gracePeriod); + }); // Listen to the captive portal when it unlocks - try { - browser.captivePortal.onStateChange.addListener( - rollout.onCaptiveStateChanged - ); - } catch (e) { - // Captive Portal Service is disabled. - } + browser.captivePortal.onConnectivityAvailable.addListener(async () => { + log("Captive portal onConnectivityAvailable, running heuristics."); + if (rollout.networkSettledTimeout) { + log("Canceling queued heuristics run."); + clearTimeout(rollout.networkSettledTimeout); + rollout.networkSettledTimeout = null; + } + + let shouldRunHeuristics = await stateManager.shouldRunHeuristics(); + + if (!shouldRunHeuristics) { + return; + } + + await this.runStartupHeuristics(); + }); }, - async onConnectionChanged({ status }) { - log("onConnectionChanged", status); + async runStartupHeuristics() { + let decision = await this.heuristics("startup"); + let shouldShowDoorhanger = await stateManager.shouldShowDoorhanger(); + if (decision === "disable_doh") { + await stateManager.setState("disabled"); - if (status != "up") { - return; - } - - let captiveState = "unknown"; - try { - captiveState = await browser.captivePortal.getState(); - } catch (e) { - // Captive Portal Service is disabled. - } - - if (captiveState == "locked_portal") { - return; - } - - // The network is up and we don't know that we're in a locked portal. - // Run heuristics. If we detect a portal later, we'll run heuristics again - // when it's unlocked. In that case, this run will likely have failed. - await rollout.heuristics("netchange"); - }, - - async onCaptiveStateChanged({ state }) { - log("onCaptiveStateChanged", state); - // unlocked_portal means we were previously in a locked portal and then - // network access was granted. - if (state == "unlocked_portal") { - await rollout.heuristics("netchange"); + // If the heuristics say to enable DoH, determine if the doorhanger + // should be shown + } else if (shouldShowDoorhanger) { + await stateManager.showDoorHangerAndEnableDoH(); + } else { + // Doorhanger has been shown before and did not opt-out + await stateManager.setState("enabled"); } }, }; diff --git a/browser/extensions/doh-rollout/experiments/doorhanger/api.js b/browser/extensions/doh-rollout/experiments/doorhanger/api.js index d792e38c1f36..efdcb05a9b28 100644 --- a/browser/extensions/doh-rollout/experiments/doorhanger/api.js +++ b/browser/extensions/doh-rollout/experiments/doorhanger/api.js @@ -7,8 +7,6 @@ /* global BrowserWindowTracker, ExtensionCommon, ExtensionAPI */ ChromeUtils.import("resource://gre/modules/Services.jsm", this); -ChromeUtils.import("resource://gre/modules/Preferences.jsm", this); -ChromeUtils.import("resource:///modules/EveryWindow.jsm", this); var { EventManager, EventEmitter } = ExtensionCommon; const { @@ -99,65 +97,7 @@ this.doorhanger = class doorhanger extends ExtensionAPI { experiments: { doorhanger: { async show(properties) { - let profileAge = await ChromeUtils.import( - "resource://gre/modules/ProfileAge.jsm", - {} - ).ProfileAge(); - - let creationDate = await profileAge.created; - let firstUse = await profileAge.firstUse; - let resetDate = await profileAge.reset; - let profileDate = resetDate || firstUse || creationDate; - - // We only need to show the doorhanger to users who have not been - // shown a version of the privacy statement that includes DoH at - // first-run. - let profileCreationThreshold = parseInt( - Preferences.get("doh-rollout.profileCreationThreshold") - ); - if ( - !isNaN(profileCreationThreshold) && - profileDate > profileCreationThreshold - ) { - return false; - } - - // Show the doorhanger next time there's a top-level location change. - let tabsProgressListener = { - onLocationChange( - aBrowser, - aWebProgress, - aRequest, - aLocationURI, - aFlags - ) { - let topWindow = getMostRecentBrowserWindow(); - // Filter out history.push/pop and subframes. - if ( - aBrowser != topWindow.gBrowser.selectedBrowser || - aFlags & - Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT || - !aWebProgress.isTopLevel - ) { - return; - } - doorhangerEventEmitter.emitShow(properties); - EveryWindow.unregisterCallback("doh-rollout"); - }, - }; - EveryWindow.registerCallback( - "doh-rollout", - win => { - win.gBrowser.addTabsProgressListener(tabsProgressListener); - }, - (win, closing) => { - if (closing) { - return; - } - win.gBrowser.removeTabsProgressListener(tabsProgressListener); - } - ); - return true; + await doorhangerEventEmitter.emitShow(properties); }, onDoorhangerAccept: new EventManager({ context, diff --git a/browser/extensions/doh-rollout/test/browser/browser.ini b/browser/extensions/doh-rollout/test/browser/browser.ini index 4a407a991922..35af1889d00c 100644 --- a/browser/extensions/doh-rollout/test/browser/browser.ini +++ b/browser/extensions/doh-rollout/test/browser/browser.ini @@ -5,7 +5,6 @@ skip-if = debug # Bug 1548006 - reloading an addon upsets the leak checker. [browser_cleanFlow.js] [browser_dirtyEnable.js] [browser_doorhangerUserReject.js] -[browser_doorhanger_newProfile.js] [browser_policyOverride.js] skip-if = (!debug && bits == 64) #Bug 1605297 [browser_userInterference.js] diff --git a/browser/extensions/doh-rollout/test/browser/browser_cleanFlow.js b/browser/extensions/doh-rollout/test/browser/browser_cleanFlow.js index 08e67a566e76..938b46bb7f07 100644 --- a/browser/extensions/doh-rollout/test/browser/browser_cleanFlow.js +++ b/browser/extensions/doh-rollout/test/browser/browser_cleanFlow.js @@ -1,7 +1,5 @@ "use strict"; -add_task(setup); - add_task(async function testCleanFlow() { // Set up a passing environment and enable DoH. setPassingHeuristics(); @@ -13,7 +11,6 @@ add_task(async function testCleanFlow() { }); is(Preferences.get(prefs.DOH_SELF_ENABLED_PREF), true, "Breadcrumb saved."); - let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, EXAMPLE_URL); let panel = await promise; is( Preferences.get(prefs.DOH_DOORHANGER_SHOWN_PREF), @@ -28,7 +25,6 @@ add_task(async function testCleanFlow() { await promise; await ensureTRRMode(2); - await checkHeuristicsTelemetry("enable_doh", "startup"); await BrowserTestUtils.waitForCondition(() => { return Preferences.get(prefs.DOH_DOORHANGER_SHOWN_PREF); @@ -49,32 +45,28 @@ add_task(async function testCleanFlow() { "Breadcrumb not cleared." ); - BrowserTestUtils.removeTab(tab); - // Change the environment to failing and simulate a network change. setFailingHeuristics(); simulateNetworkChange(); await ensureTRRMode(0); - await checkHeuristicsTelemetry("disable_doh", "netchange"); // Trigger another network change. simulateNetworkChange(); await ensureNoTRRModeChange(0); - await checkHeuristicsTelemetry("disable_doh", "netchange"); // Restart the add-on for good measure. await restartAddon(); await ensureNoTRRModeChange(0); - await checkHeuristicsTelemetry("disable_doh", "startup"); // Set a passing environment and simulate a network change. setPassingHeuristics(); simulateNetworkChange(); await ensureTRRMode(2); - await checkHeuristicsTelemetry("enable_doh", "netchange"); // Again, repeat and check nothing changed. simulateNetworkChange(); await ensureNoTRRModeChange(2); - await checkHeuristicsTelemetry("enable_doh", "netchange"); + + // Clean up. + await resetPrefsAndRestartAddon(); }); diff --git a/browser/extensions/doh-rollout/test/browser/browser_dirtyEnable.js b/browser/extensions/doh-rollout/test/browser/browser_dirtyEnable.js index 87f1d1e475d5..5f5f566d4cda 100644 --- a/browser/extensions/doh-rollout/test/browser/browser_dirtyEnable.js +++ b/browser/extensions/doh-rollout/test/browser/browser_dirtyEnable.js @@ -1,7 +1,5 @@ "use strict"; -add_task(setup); - add_task(async function testDirtyEnable() { // Set up a failing environment, pre-set DoH to enabled, and verify that // when the add-on is enabled, it doesn't do anything - DoH remains turned on. @@ -22,20 +20,19 @@ add_task(async function testDirtyEnable() { "Breadcrumb not saved." ); await ensureNoTRRModeChange(2); - checkHeuristicsTelemetry("prefHasUserValue", "first_run"); // Simulate a network change. simulateNetworkChange(); await ensureNoTRRModeChange(2); - ensureNoHeuristicsTelemetry(); // Restart for good measure. await restartAddon(); await ensureNoTRRModeChange(2); - ensureNoHeuristicsTelemetry(); // Simulate a network change. simulateNetworkChange(); await ensureNoTRRModeChange(2); - ensureNoHeuristicsTelemetry(); + + // Clean up. + await resetPrefsAndRestartAddon(); }); diff --git a/browser/extensions/doh-rollout/test/browser/browser_doorhangerUserReject.js b/browser/extensions/doh-rollout/test/browser/browser_doorhangerUserReject.js index 2fa36779d804..52f9635332cd 100644 --- a/browser/extensions/doh-rollout/test/browser/browser_doorhangerUserReject.js +++ b/browser/extensions/doh-rollout/test/browser/browser_doorhangerUserReject.js @@ -1,7 +1,5 @@ "use strict"; -add_task(setup); - add_task(async function testDoorhangerUserReject() { // Set up a passing environment and enable DoH. setPassingHeuristics(); @@ -13,7 +11,6 @@ add_task(async function testDoorhangerUserReject() { }); is(Preferences.get(prefs.DOH_SELF_ENABLED_PREF), true, "Breadcrumb saved."); - let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, EXAMPLE_URL); let panel = await promise; is( Preferences.get(prefs.DOH_DOORHANGER_SHOWN_PREF), @@ -22,7 +19,6 @@ add_task(async function testDoorhangerUserReject() { ); await ensureTRRMode(2); - await checkHeuristicsTelemetry("enable_doh", "startup"); // Click the doorhanger's "reject" button. let button = panel.querySelector(".popup-notification-secondary-button"); @@ -50,24 +46,21 @@ add_task(async function testDoorhangerUserReject() { "Breadcrumb cleared." ); - BrowserTestUtils.removeTab(tab); - await ensureTRRMode(5); - await checkHeuristicsTelemetry("disable_doh", "doorhangerDecline"); // Simulate a network change. simulateNetworkChange(); await ensureNoTRRModeChange(5); - ensureNoHeuristicsTelemetry(); // Restart the add-on for good measure. await restartAddon(); await ensureNoTRRModeChange(5); - ensureNoHeuristicsTelemetry(); // Set failing environment and trigger another network change. setFailingHeuristics(); simulateNetworkChange(); await ensureNoTRRModeChange(5); - ensureNoHeuristicsTelemetry(); + + // Clean up. + await resetPrefsAndRestartAddon(); }); diff --git a/browser/extensions/doh-rollout/test/browser/browser_doorhanger_newProfile.js b/browser/extensions/doh-rollout/test/browser/browser_doorhanger_newProfile.js deleted file mode 100644 index a2b3ba29b49c..000000000000 --- a/browser/extensions/doh-rollout/test/browser/browser_doorhanger_newProfile.js +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; - -add_task(setup); - -add_task(async function testDoorhanger() { - Preferences.reset(prefs.PROFILE_CREATION_THRESHOLD_PREF); - // Set up a passing environment and enable DoH. - setPassingHeuristics(); - Preferences.set(prefs.DOH_ENABLED_PREF, true); - - await BrowserTestUtils.waitForCondition(() => { - return Preferences.get(prefs.DOH_SELF_ENABLED_PREF); - }); - is(Preferences.get(prefs.DOH_SELF_ENABLED_PREF), true, "Breadcrumb saved."); - - await BrowserTestUtils.waitForCondition(() => { - return Preferences.get(prefs.DOH_DOORHANGER_SHOWN_PREF); - }); - is( - Preferences.get(prefs.DOH_DOORHANGER_SHOWN_PREF), - true, - "Doorhanger shown pref saved." - ); - is( - Preferences.get(prefs.DOH_DOORHANGER_USER_DECISION_PREF), - "NewProfile", - "Doorhanger decision saved." - ); - is( - Preferences.get(prefs.DOH_SELF_ENABLED_PREF), - true, - "Breadcrumb not cleared." - ); -}); diff --git a/browser/extensions/doh-rollout/test/browser/browser_policyOverride.js b/browser/extensions/doh-rollout/test/browser/browser_policyOverride.js index 2169483fcee4..74314c68412f 100644 --- a/browser/extensions/doh-rollout/test/browser/browser_policyOverride.js +++ b/browser/extensions/doh-rollout/test/browser/browser_policyOverride.js @@ -1,7 +1,5 @@ "use strict"; -add_task(setup); - const { EnterprisePolicyTesting } = ChromeUtils.import( "resource://testing-common/EnterprisePolicyTesting.jsm", null @@ -38,28 +36,25 @@ add_task(async function testPolicyOverride() { "Breadcrumb not saved." ); await ensureNoTRRModeChange(0); - await checkHeuristicsTelemetry("policy_without_doh", "first_run"); // Simulate a network change. simulateNetworkChange(); await ensureNoTRRModeChange(0); - ensureNoHeuristicsTelemetry(); // Restart for good measure. await restartAddon(); await ensureNoTRRModeChange(0); - await checkHeuristicsTelemetry("policy_without_doh", "startup"); // Simulate a network change. simulateNetworkChange(); await ensureNoTRRModeChange(0); - ensureNoHeuristicsTelemetry(); // Clean up. await EnterprisePolicyTesting.setupPolicyEngineWithJson({ policies: {}, }); EnterprisePolicyTesting.resetRunOnceState(); + await resetPrefsAndRestartAddon(); is( Services.policies.status, diff --git a/browser/extensions/doh-rollout/test/browser/browser_userInterference.js b/browser/extensions/doh-rollout/test/browser/browser_userInterference.js index 4f611c086250..3bbc0c599027 100644 --- a/browser/extensions/doh-rollout/test/browser/browser_userInterference.js +++ b/browser/extensions/doh-rollout/test/browser/browser_userInterference.js @@ -1,7 +1,5 @@ "use strict"; -add_task(setup); - add_task(async function testUserInterference() { // Set up a passing environment and enable DoH. setPassingHeuristics(); @@ -13,7 +11,6 @@ add_task(async function testUserInterference() { }); is(Preferences.get(prefs.DOH_SELF_ENABLED_PREF), true, "Breadcrumb saved."); - let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, EXAMPLE_URL); let panel = await promise; is( Preferences.get(prefs.DOH_DOORHANGER_SHOWN_PREF), @@ -42,10 +39,7 @@ add_task(async function testUserInterference() { "Doorhanger decision saved." ); - BrowserTestUtils.removeTab(tab); - await ensureTRRMode(2); - await checkHeuristicsTelemetry("enable_doh", "startup"); // Set the TRR mode pref manually and ensure we respect this. Preferences.set(prefs.TRR_MODE_PREF, 0); @@ -53,7 +47,6 @@ add_task(async function testUserInterference() { // Simulate a network change. simulateNetworkChange(); await ensureNoTRRModeChange(0); - await checkHeuristicsTelemetry("disable_doh", "userModified"); is( Preferences.get(prefs.DOH_DISABLED_PREF, false), @@ -69,15 +62,15 @@ add_task(async function testUserInterference() { // Simulate another network change. simulateNetworkChange(); await ensureNoTRRModeChange(0); - ensureNoHeuristicsTelemetry(); // Restart the add-on for good measure. await restartAddon(); await ensureNoTRRModeChange(0); - ensureNoHeuristicsTelemetry(); // Simulate another network change. simulateNetworkChange(); await ensureNoTRRModeChange(0); - ensureNoHeuristicsTelemetry(); + + // Clean up. + await resetPrefsAndRestartAddon(); }); diff --git a/browser/extensions/doh-rollout/test/browser/head.js b/browser/extensions/doh-rollout/test/browser/head.js index cc574f09ff81..f850c34d46b1 100644 --- a/browser/extensions/doh-rollout/test/browser/head.js +++ b/browser/extensions/doh-rollout/test/browser/head.js @@ -12,14 +12,12 @@ ChromeUtils.defineModuleGetter( "resource://gre/modules/Preferences.jsm" ); -const { CommonUtils } = ChromeUtils.import( - "resource://services-common/utils.js" -); +SpecialPowers.pushPrefEnv({ + set: [["security.notification_enable_delay", 0]], +}); const ADDON_ID = "doh-rollout@mozilla.org"; -const EXAMPLE_URL = "https://example.com/"; - const prefs = { DOH_ENABLED_PREF: "doh-rollout.enabled", TRR_MODE_PREF: "network.trr.mode", @@ -33,7 +31,6 @@ const prefs = { DOH_BALROG_MIGRATION_PREF: "doh-rollout.balrog-migration-done", DOH_DEBUG_PREF: "doh-rollout.debug", MOCK_HEURISTICS_PREF: "doh-rollout.heuristics.mockValues", - PROFILE_CREATION_THRESHOLD_PREF: "doh-rollout.profileCreationThreshold", }; const fakePassingHeuristics = JSON.stringify({ @@ -58,65 +55,6 @@ const fakeFailingHeuristics = JSON.stringify({ policy: "disable_doh", }); -async function setup() { - SpecialPowers.pushPrefEnv({ - set: [["security.notification_enable_delay", 0]], - }); - let oldCanRecord = Services.telemetry.canRecordExtended; - Services.telemetry.canRecordExtended = true; - Services.telemetry.clearEvents(); - - // Set the profile creation threshold to very far in the future by defualt, - // so that we can test the doorhanger. browser_doorhanger_newProfile.js - // overrides this. - Preferences.set(prefs.PROFILE_CREATION_THRESHOLD_PREF, "99999999999999"); - - registerCleanupFunction(async () => { - Services.telemetry.canRecordExtended = oldCanRecord; - Services.telemetry.clearEvents(); - await resetPrefsAndRestartAddon(); - }); -} - -async function checkHeuristicsTelemetry(decision, evaluateReason) { - let events; - await BrowserTestUtils.waitForCondition(() => { - events = Services.telemetry.snapshotEvents( - Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS - ).dynamic; - return events; - }); - events = events.filter( - e => e[1] == "doh" && e[2] == "evaluate" && e[3] == "heuristics" - ); - is(events.length, 1, "Found the expected heuristics event."); - is(events[0][4], decision, "The event records the expected decision"); - if (evaluateReason) { - is(events[0][5].evaluateReason, evaluateReason, "Got the expected reason."); - } - - // After checking the event, clear all telemetry. Since we check for a single - // event above, this ensures all heuristics events are intentional and tested. - // TODO: Test events other than heuristics. Those tests would also work the - // same way, so as to test one event at a time, and this clearEvents() call - // will continue to exist as-is. - Services.telemetry.clearEvents(); -} - -function ensureNoHeuristicsTelemetry() { - let events = Services.telemetry.snapshotEvents( - Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS - ).dynamic; - if (!events) { - ok(true, "Found no heuristics events."); - return; - } - events = events.filter( - e => e[1] == "doh" && e[2] == "evaluate" && e[3] == "heuristics" - ); - is(events.length, 0, "Found no heuristics events."); -} - function setPassingHeuristics() { Preferences.set(prefs.MOCK_HEURISTICS_PREF, fakePassingHeuristics); } @@ -153,12 +91,7 @@ async function waitForDoorhanger() { } function simulateNetworkChange() { - // The networkStatus API does not actually propagate the link status we supply - // here, but rather sends the link status from the NetworkLinkService. - // This means there's no point sending a down and then an up - the extension - // will just receive "up" twice. - // TODO: Implement a mock NetworkLinkService and use it to also simulate - // network down events. + Services.obs.notifyObservers(null, "network:link-status-changed", "down"); Services.obs.notifyObservers(null, "network:link-status-changed", "up"); }