Bug 1829342 - Event telemetry for warning page loading and button clicking, r=valentin,Gijs

Differential Revision: https://phabricator.services.mozilla.com/D176248
This commit is contained in:
Kershaw Chang 2023-04-27 15:43:35 +00:00
Родитель 042a597aba
Коммит 89ee563ed5
8 изменённых файлов: 264 добавлений и 11 удалений

Просмотреть файл

@ -11,6 +11,7 @@ function reset() {
Services.prefs.clearUserPref("network.dns.native-is-localhost");
Services.prefs.clearUserPref("doh-rollout.disable-heuristics");
Services.prefs.setIntPref("network.proxy.type", oldProxyType);
Services.prefs.clearUserPref("network.trr.uri");
Services.dns.setHeuristicDetectionResult(Ci.nsITRRSkipReason.TRR_OK);
}
@ -39,6 +40,17 @@ async function verifyLoad(url, testName) {
// This helper verifies that loading the given url will lead to an error -- the fallback warning if the parameter is true
async function verifyError(url, fallbackWarning, testName) {
// Clear everything.
Services.telemetry.clearEvents();
await TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
true
).content;
return !events || !events.length;
});
Services.telemetry.setEventRecordingEnabled("security.doh.neterror", true);
let browser;
let pageLoaded;
await BrowserTestUtils.openNewForegroundTab(
@ -80,6 +92,29 @@ async function verifyError(url, fallbackWarning, testName) {
}
);
if (fallbackWarning) {
let loadEvent = await TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
true
).content;
return events?.find(
e => e[1] == "security.doh.neterror" && e[2] == "load"
);
}, "recorded telemetry for the load");
loadEvent.shift();
Assert.deepEqual(loadEvent, [
"security.doh.neterror",
"load",
"dohwarning",
"NativeFallbackWarning",
{
mode: "2",
provider_key: "0.0.0.0",
skip_reason: "TRR_HEURISTIC_TRIPPED_CANARY",
},
]);
}
BrowserTestUtils.removeTab(gBrowser.selectedTab);
}

Просмотреть файл

@ -10,11 +10,7 @@ function resetPrefs() {
Services.prefs.setIntPref("network.proxy.type", oldProxyType);
}
// This test makes sure that the Add exception button only shows up
// when the skipReason indicates that the domain could not be resolved.
// If instead there is a problem with the TRR connection, then we don't
// show the exception button.
add_task(async function exceptionButtonTRROnly() {
async function loadErrorPage() {
Services.prefs.setBoolPref("network.dns.native-is-localhost", true);
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY);
// We need to disable proxy, otherwise TRR isn't used for name resolution.
@ -38,6 +34,15 @@ add_task(async function exceptionButtonTRROnly() {
info("Loading and waiting for the net error");
await pageLoaded;
return browser;
}
// This test makes sure that the Add exception button only shows up
// when the skipReason indicates that the domain could not be resolved.
// If instead there is a problem with the TRR connection, then we don't
// show the exception button.
add_task(async function exceptionButtonTRROnly() {
let browser = await loadErrorPage();
await SpecialPowers.spawn(browser, [], function() {
const doc = content.document;
@ -65,3 +70,101 @@ add_task(async function exceptionButtonTRROnly() {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
resetPrefs();
});
add_task(async function TRROnlyExceptionButtonTelemetry() {
// Clear everything.
Services.telemetry.clearEvents();
await TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
true
).content;
return !events || !events.length;
});
Services.telemetry.setEventRecordingEnabled("security.doh.neterror", true);
let browser = await loadErrorPage();
await SpecialPowers.spawn(browser, [], function() {
const doc = content.document;
ok(
doc.documentURI.startsWith("about:neterror"),
"Should be showing error page"
);
let buttons = ["neterrorTryAgainButton", "trrSettingsButton"];
for (let buttonId of buttons) {
let button = doc.getElementById(buttonId);
button.click();
}
});
is(
gBrowser.tabs.length,
3,
"Should open about:preferences#privacy-doh in another tab"
);
let loadEvent = await TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
true
).content;
return events?.find(e => e[1] == "security.doh.neterror" && e[2] == "load");
}, "recorded telemetry for the load");
loadEvent.shift();
Assert.deepEqual(loadEvent, [
"security.doh.neterror",
"load",
"dohwarning",
"TRROnlyFailure",
{
mode: "3",
provider_key: "mozilla.cloudflare-dns.com",
skip_reason: "TRR_UNKNOWN_CHANNEL_FAILURE",
},
]);
let clickEvents = await TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
true
).content;
return events?.filter(
e => e[1] == "security.doh.neterror" && e[2] == "click"
);
}, "recorded telemetry for clicking buttons");
let firstEvent = clickEvents[0];
firstEvent.shift(); // remove timestamp
Assert.deepEqual(firstEvent, [
"security.doh.neterror",
"click",
"try_again_button",
"TRROnlyFailure",
{
mode: "3",
provider_key: "mozilla.cloudflare-dns.com",
skip_reason: "TRR_UNKNOWN_CHANNEL_FAILURE",
},
]);
let secondEvent = clickEvents[1];
secondEvent.shift(); // remove timestamp
Assert.deepEqual(secondEvent, [
"security.doh.neterror",
"click",
"settings_button",
"TRROnlyFailure",
{
mode: "3",
provider_key: "mozilla.cloudflare-dns.com",
skip_reason: "TRR_UNKNOWN_CHANNEL_FAILURE",
},
]);
BrowserTestUtils.removeTab(gBrowser.tabs[2]);
BrowserTestUtils.removeTab(gBrowser.tabs[1]);
resetPrefs();
});

Просмотреть файл

@ -1704,6 +1704,8 @@ BrowserGlue.prototype = {
true
);
Services.telemetry.setEventRecordingEnabled("security.doh.neterror", true);
lazy.PageActions.init();
lazy.DoHController.init();

Просмотреть файл

@ -32,6 +32,7 @@ export class NetErrorChild extends RemotePageChild {
"RPMGetTRRDomain",
"RPMIsSiteSpecificTRRError",
"RPMSetTRRDisabledLoadFlags",
"RPMGetCurrentTRRMode",
];
this.exportFunctions(exportableFunctions);
}

Просмотреть файл

@ -3204,6 +3204,51 @@ security.doh.trrPerformance:
products:
- firefox
security.doh.neterror:
load:
objects: ["dohwarning"]
bug_numbers:
- 1829342
description: >
The DoH warning page is loaded.
expiry_version: never
notification_emails:
- necko@mozilla.com
- kershaw@mozilla.com
release_channel_collection: opt-out
products:
- "firefox"
record_in_processes: ["content"]
extra_keys:
mode: Current TRR mode
provider_key: TRR provider
skip_reason: The reason why DoH request is failed
click:
objects: [
"try_again_button",
"add_exception_button",
"settings_button",
"continue_button",
"disable_warning",
"learn_more_link",
]
bug_numbers:
- 1829342
description: >
User interaction by click buttons on the DoH warning page.
expiry_version: never
notification_emails:
- necko@mozilla.com
- kershaw@mozilla.com
release_channel_collection: opt-out
products:
- "firefox"
record_in_processes: ["content"]
extra_keys:
mode: Current TRR mode
provider_key: TRR provider
skip_reason: The reason why DoH request is failed
security.ui.certerror:
load:
objects: ["aboutcerterror"]

Просмотреть файл

@ -251,6 +251,45 @@ function disallowCertOverridesIfNeeded() {
}
}
function recordTRREventTelemetry(
warningPageType,
trrMode,
trrDomain,
skipReason
) {
RPMRecordTelemetryEvent(
"security.doh.neterror",
"load",
"dohwarning",
warningPageType,
{
mode: trrMode,
provider_key: trrDomain,
skip_reason: skipReason,
}
);
const netErrorButtonDiv = document.getElementById("netErrorButtonContainer");
const buttons = netErrorButtonDiv.querySelectorAll("button");
for (let b of buttons) {
b.addEventListener("click", function(e) {
let target = e.originalTarget;
let telemetryId = target.dataset.telemetryId;
RPMRecordTelemetryEvent(
"security.doh.neterror",
"click",
telemetryId,
warningPageType,
{
mode: trrMode,
provider_key: trrDomain,
skip_reason: skipReason,
}
);
});
}
}
function initPage() {
// We show an offline support page in case of a system-wide error,
// when a user cannot connect to the internet and access the SUMO website.
@ -450,7 +489,7 @@ function initPage() {
RPMSendQuery("Browser:AddTRRExcludedDomain", {
hostname: HOST_NAME,
}).then(msg => {
retryThis(this);
retryThis(trrExceptionButton);
});
});
@ -506,6 +545,14 @@ function initPage() {
descriptionTag = "neterror-dns-not-found-trr-server-problem";
}
let trrMode = RPMGetIntPref("network.trr.mode").toString();
recordTRREventTelemetry(
"TRROnlyFailure",
trrMode,
args.trrDomain,
skipReason
);
let description = document.getElementById("trrOnlyDescription");
document.l10n.setAttributes(description, descriptionTag, args);
@ -522,6 +569,17 @@ function initPage() {
trrOnlyLearnMoreLink.addEventListener("click", event => {
event.preventDefault();
RPMSendAsyncMessage("OpenTRRPreferences");
RPMRecordTelemetryEvent(
"security.doh.neterror",
"click",
"settings_button",
"TRROnlyFailure",
{
mode: trrMode,
provider_key: args.trrDomain,
skip_reason: skipReason,
}
);
});
} else {
// This will be replaced at a later point with a link to an offline support page
@ -622,6 +680,13 @@ function showNativeFallbackWarning() {
let div = document.getElementById("nativeFallbackContainer");
div.hidden = false;
recordTRREventTelemetry(
"NativeFallbackWarning",
RPMGetIntPref("network.trr.mode").toString(),
args.trrDomain,
skipReason
);
}
/**
* Builds HTML elements from `parts` and appends them to `parentElement`.

Просмотреть файл

@ -89,11 +89,11 @@
</div>
<div id="netErrorButtonContainer" class="button-container" hidden="">
<button class="primary try-again" data-l10n-id="neterror-try-again-button"></button>
<button id="trrExceptionButton" data-l10n-id="neterror-add-exception-button" hidden=""></button>
<button id="trrSettingsButton" data-l10n-id="neterror-settings-button" hidden=""></button>
<button id="nativeFallbackContinueThisTimeButton" data-l10n-id="neterror-trr-continue-this-time" hidden=""></button>
<button id="nativeFallbackIgnoreButton" data-l10n-id="neterror-disable-native-feedback-warning" hidden=""></button>
<button id="neterrorTryAgainButton" class="primary try-again" data-l10n-id="neterror-try-again-button" data-telemetry-id="try_again_button"></button>
<button id="trrExceptionButton" data-l10n-id="neterror-add-exception-button" data-telemetry-id="add_exception_button" hidden=""></button>
<button id="trrSettingsButton" data-l10n-id="neterror-settings-button" data-telemetry-id="settings_button" hidden=""></button>
<button id="nativeFallbackContinueThisTimeButton" data-l10n-id="neterror-trr-continue-this-time" data-telemetry-id="continue_button" hidden=""></button>
<button id="nativeFallbackIgnoreButton" data-l10n-id="neterror-disable-native-feedback-warning" data-telemetry-id="disable_warning" hidden=""></button>
</div>
<div class="advanced-panel-container">

Просмотреть файл

@ -88,6 +88,7 @@ export let RemotePageAccessManager = {
"OpenTRRPreferences",
],
RPMCheckAlternateHostAvailable: ["*"],
RPMRecordTelemetryEvent: ["security.doh.neterror"],
RPMAddMessageListener: ["*"],
RPMRemoveMessageListener: ["*"],
RPMGetFormatURLPref: [
@ -115,6 +116,7 @@ export let RemotePageAccessManager = {
RPMIsSiteSpecificTRRError: ["*"],
RPMSetTRRDisabledLoadFlags: ["*"],
RPMSendQuery: ["Browser:AddTRRExcludedDomain"],
RPMGetIntPref: ["network.trr.mode"],
},
"about:newtab": {
RPMSendAsyncMessage: ["ActivityStream:ContentToMain"],