mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1868380 - Add glean telemetry for HTTPS-First r=freddyb,simonf
- Add new glean metrics.yaml for dom/security - Add 8 new metrics for (schemeless) HTTPS-First, see metrics.yaml for explanation - Add getter for timing on document load listener - Provide `nsHTTPSOnlyUtils::PotentiallyDowngradeHttpsFirstRequest` with complete document load listener so that it is able to access the timing - Adapt browser_httpsfirst.js and browser_schemeless.js tests to also check for correct telemetry values Differential Revision: https://phabricator.services.mozilla.com/D196072
This commit is contained in:
parent
e5cdcfa441
commit
aafba62d3d
153
dom/security/metrics.yaml
Normal file
153
dom/security/metrics.yaml
Normal file
@ -0,0 +1,153 @@
|
||||
# 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/.
|
||||
|
||||
# Adding a new metric? We have docs for that!
|
||||
# https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/new_definitions_file.html
|
||||
|
||||
---
|
||||
$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
|
||||
$tags:
|
||||
- 'Core :: DOM: Security'
|
||||
|
||||
httpsfirst:
|
||||
upgraded:
|
||||
type: counter
|
||||
description: >
|
||||
Counts how often a load is marked to be upgraded to HTTPS because of
|
||||
HTTPS-First (`dom.security.https_first` enabled).
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380#c10
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- mjurgens@mozilla.com
|
||||
- seceng-telemetry@mozilla.com
|
||||
expires: never
|
||||
|
||||
upgraded_schemeless:
|
||||
type: counter
|
||||
description: >
|
||||
Counts how often a load is marked to be upgraded to HTTPS because of
|
||||
schemeless HTTPS-First (`dom.security.https_first` disabled, but load
|
||||
marked as schemeless).
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380#c10
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- mjurgens@mozilla.com
|
||||
- seceng-telemetry@mozilla.com
|
||||
expires: never
|
||||
|
||||
downgraded:
|
||||
type: counter
|
||||
description: >
|
||||
How many regular HTTPS-First (`dom.security.https_first` enabled)
|
||||
upgrades get downgraded again.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380#c10
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- mjurgens@mozilla.com
|
||||
- seceng-telemetry@mozilla.com
|
||||
expires: never
|
||||
|
||||
downgraded_schemeless:
|
||||
type: counter
|
||||
description: >
|
||||
How many schemeless HTTPS-First (`dom.security.https_first` disabled, but
|
||||
load marked as schemeless) upgrades get downgraded again.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380#c10
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- mjurgens@mozilla.com
|
||||
- seceng-telemetry@mozilla.com
|
||||
expires: never
|
||||
|
||||
downgraded_on_timer:
|
||||
type: rate
|
||||
description: >
|
||||
How many HTTPS-First (`dom.security.https_first` enabled) upgrades get
|
||||
downgraded again because the HTTP request fired after 3s received a answer
|
||||
faster than the HTTPS request.
|
||||
denominator_metric: httpsfirst.downgraded
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380#c10
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- mjurgens@mozilla.com
|
||||
- seceng-telemetry@mozilla.com
|
||||
expires: never
|
||||
|
||||
downgraded_on_timer_schemeless:
|
||||
type: rate
|
||||
description: >
|
||||
How many of schemeless HTTPS-First (`dom.security.https_first` disabled,
|
||||
but load marked as schemeless) upgrades get downgraded again because the
|
||||
HTTP request fired after 3s received a answer faster than the HTTPS
|
||||
request
|
||||
denominator_metric: httpsfirst.downgraded_schemeless
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380#c10
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- mjurgens@mozilla.com
|
||||
- seceng-telemetry@mozilla.com
|
||||
expires: never
|
||||
|
||||
downgrade_time:
|
||||
type: timing_distribution
|
||||
description: >
|
||||
If a HTTPS-First (`dom.security.https_first` enabled) upgrade isn't
|
||||
successful, measures the timespan between the navigation start and the
|
||||
downgrade. This is essentially the overhead caused by HTTPS-First if a
|
||||
site does not support HTTPS.
|
||||
time_unit: millisecond
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380#c10
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- mjurgens@mozilla.com
|
||||
- seceng-telemetry@mozilla.com
|
||||
expires: never
|
||||
|
||||
downgrade_time_schemeless:
|
||||
type: timing_distribution
|
||||
description: >
|
||||
If a schemeless HTTPS-First (`dom.security.https_first` disabled, but
|
||||
load marked as schemeless) upgrade isn't successful, measures the
|
||||
timespan between the navigation start and the downgrade. This is
|
||||
essentially the overhead caused by HTTPS-First if a site does not support
|
||||
HTTPS.
|
||||
time_unit: millisecond
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1868380#c10
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- mjurgens@mozilla.com
|
||||
- seceng-telemetry@mozilla.com
|
||||
expires: never
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "mozilla/Components.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/glean/GleanMetrics.h"
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
@ -438,7 +440,7 @@ bool nsHTTPSOnlyUtils::ShouldUpgradeHttpsFirstRequest(nsIURI* aURI,
|
||||
// We can upgrade the request - let's log to the console and set the status
|
||||
// so we know that we upgraded the request.
|
||||
if (aLoadInfo->GetWasSchemelessInput() &&
|
||||
mozilla::StaticPrefs::dom_security_https_first_schemeless()) {
|
||||
!IsHttpsFirstModeEnabled(isPrivateWin)) {
|
||||
nsAutoCString urlCString;
|
||||
aURI->GetSpec(urlCString);
|
||||
NS_ConvertUTF8toUTF16 urlString(urlCString);
|
||||
@ -447,6 +449,8 @@ bool nsHTTPSOnlyUtils::ShouldUpgradeHttpsFirstRequest(nsIURI* aURI,
|
||||
nsHTTPSOnlyUtils::LogLocalizedString("HTTPSFirstSchemeless", params,
|
||||
nsIScriptError::warningFlag, aLoadInfo,
|
||||
aURI, true);
|
||||
|
||||
mozilla::glean::httpsfirst::upgraded_schemeless.Add();
|
||||
} else {
|
||||
nsAutoCString scheme;
|
||||
|
||||
@ -461,7 +465,12 @@ bool nsHTTPSOnlyUtils::ShouldUpgradeHttpsFirstRequest(nsIURI* aURI,
|
||||
isSpeculative ? "HTTPSOnlyUpgradeSpeculativeConnection"
|
||||
: "HTTPSOnlyUpgradeRequest",
|
||||
params, nsIScriptError::warningFlag, aLoadInfo, aURI, true);
|
||||
|
||||
if (!isSpeculative) {
|
||||
mozilla::glean::httpsfirst::upgraded.Add();
|
||||
}
|
||||
}
|
||||
|
||||
// Set flag so we know that we upgraded the request
|
||||
httpsOnlyStatus |= nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST;
|
||||
aLoadInfo->SetHttpsOnlyStatus(httpsOnlyStatus);
|
||||
@ -470,9 +479,11 @@ bool nsHTTPSOnlyUtils::ShouldUpgradeHttpsFirstRequest(nsIURI* aURI,
|
||||
|
||||
/* static */
|
||||
already_AddRefed<nsIURI>
|
||||
nsHTTPSOnlyUtils::PotentiallyDowngradeHttpsFirstRequest(nsIChannel* aChannel,
|
||||
nsresult aStatus) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
nsHTTPSOnlyUtils::PotentiallyDowngradeHttpsFirstRequest(
|
||||
mozilla::net::DocumentLoadListener* aDocumentLoadListener,
|
||||
nsresult aStatus) {
|
||||
nsCOMPtr<nsIChannel> channel = aDocumentLoadListener->GetChannel();
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
uint32_t httpsOnlyStatus = loadInfo->GetHttpsOnlyStatus();
|
||||
// Only downgrade if we this request was upgraded using HTTPS-First Mode
|
||||
if (!(httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) {
|
||||
@ -488,7 +499,7 @@ nsHTTPSOnlyUtils::PotentiallyDowngradeHttpsFirstRequest(nsIChannel* aChannel,
|
||||
// to check each NS_OK for those errors.
|
||||
// Only downgrade an NS_OK status if it is an 4xx or 5xx error.
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
|
||||
// If no httpChannel exists we have nothing to do here.
|
||||
if (!httpChannel) {
|
||||
return nullptr;
|
||||
@ -532,7 +543,7 @@ nsHTTPSOnlyUtils::PotentiallyDowngradeHttpsFirstRequest(nsIChannel* aChannel,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
|
||||
nsresult rv = channel->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsAutoCString spec;
|
||||
@ -584,6 +595,33 @@ nsHTTPSOnlyUtils::PotentiallyDowngradeHttpsFirstRequest(nsIChannel* aChannel,
|
||||
nsIScriptError::warningFlag, loadInfo,
|
||||
uri, true);
|
||||
|
||||
// Record telemety
|
||||
nsDOMNavigationTiming* timing = aDocumentLoadListener->GetTiming();
|
||||
if (timing) {
|
||||
mozilla::TimeStamp navigationStart = timing->GetNavigationStartTimeStamp();
|
||||
if (navigationStart) {
|
||||
mozilla::TimeDuration duration =
|
||||
mozilla::TimeStamp::Now() - navigationStart;
|
||||
bool isPrivateWin =
|
||||
loadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
|
||||
|
||||
if (loadInfo->GetWasSchemelessInput() &&
|
||||
!IsHttpsFirstModeEnabled(isPrivateWin)) {
|
||||
mozilla::glean::httpsfirst::downgraded_schemeless.Add();
|
||||
if (timing) {
|
||||
mozilla::glean::httpsfirst::downgrade_time_schemeless
|
||||
.AccumulateRawDuration(duration);
|
||||
}
|
||||
} else {
|
||||
mozilla::glean::httpsfirst::downgraded.Add();
|
||||
if (timing) {
|
||||
mozilla::glean::httpsfirst::downgrade_time.AccumulateRawDuration(
|
||||
duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newURI.forget();
|
||||
}
|
||||
|
||||
@ -954,6 +992,19 @@ TestHTTPAnswerRunnable::OnStartRequest(nsIRequest* aRequest) {
|
||||
nsresult httpsOnlyChannelStatus;
|
||||
httpsOnlyChannel->GetStatus(&httpsOnlyChannelStatus);
|
||||
if (httpsOnlyChannelStatus == NS_OK) {
|
||||
bool isPrivateWin =
|
||||
loadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
|
||||
if (!nsHTTPSOnlyUtils::IsHttpsOnlyModeEnabled(isPrivateWin)) {
|
||||
// Record HTTPS-First Telemetry
|
||||
if (loadInfo->GetWasSchemelessInput() &&
|
||||
!nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) {
|
||||
mozilla::glean::httpsfirst::downgraded_on_timer_schemeless
|
||||
.AddToNumerator();
|
||||
} else {
|
||||
mozilla::glean::httpsfirst::downgraded_on_timer.AddToNumerator();
|
||||
}
|
||||
}
|
||||
|
||||
httpsOnlyChannel->Cancel(NS_ERROR_NET_TIMEOUT_EXTERNAL);
|
||||
}
|
||||
}
|
||||
|
@ -95,12 +95,13 @@ class nsHTTPSOnlyUtils {
|
||||
/**
|
||||
* Determines if the request was previously upgraded with HTTPS-First, creates
|
||||
* a downgraded URI and logs to console.
|
||||
* @param aStatus Status code
|
||||
* @param aChannel Failed channel
|
||||
* @return URI with http-scheme or nullptr
|
||||
* @param aStatus Status code
|
||||
* @param aDocumentLoadListener Failed document load listener
|
||||
* @return URI with http-scheme or nullptr
|
||||
*/
|
||||
static already_AddRefed<nsIURI> PotentiallyDowngradeHttpsFirstRequest(
|
||||
nsIChannel* aChannel, nsresult aStatus);
|
||||
mozilla::net::DocumentLoadListener* aDocumentLoadListener,
|
||||
nsresult aStatus);
|
||||
|
||||
/**
|
||||
* Checks if the error code is on a block-list of codes that are probably
|
||||
|
@ -31,6 +31,7 @@ add_task(async function () {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.security.https_first", false]],
|
||||
});
|
||||
Services.fog.testResetFOG();
|
||||
|
||||
await runPrefTest(
|
||||
"http://example.com",
|
||||
@ -42,6 +43,23 @@ add_task(async function () {
|
||||
set: [["dom.security.https_first", true]],
|
||||
});
|
||||
|
||||
for (const key of [
|
||||
"upgraded",
|
||||
"upgradedSchemeless",
|
||||
"downgraded",
|
||||
"downgradedSchemeless",
|
||||
"downgradedOnTimer",
|
||||
"downgradedOnTimerSchemeless",
|
||||
"downgradeTime",
|
||||
"downgradeTimeSchemeless",
|
||||
]) {
|
||||
is(
|
||||
Glean.httpsfirst[key].testGetValue(),
|
||||
null,
|
||||
`No telemetry should have been recorded yet for ${key}`
|
||||
);
|
||||
}
|
||||
|
||||
await runPrefTest(
|
||||
"http://example.com",
|
||||
"Should upgrade upgradeable website",
|
||||
@ -71,4 +89,21 @@ add_task(async function () {
|
||||
"Should downgrade after timeout.",
|
||||
"http://"
|
||||
);
|
||||
|
||||
info("Checking expected telemetry");
|
||||
is(Glean.httpsfirst.upgraded.testGetValue(), 5);
|
||||
is(Glean.httpsfirst.upgradedSchemeless.testGetValue(), null);
|
||||
is(Glean.httpsfirst.downgraded.testGetValue(), 3);
|
||||
is(Glean.httpsfirst.downgradedSchemeless.testGetValue(), null);
|
||||
is(Glean.httpsfirst.downgradedOnTimer.testGetValue().numerator, 1);
|
||||
is(Glean.httpsfirst.downgradedOnTimerSchemeless.testGetValue(), null);
|
||||
const downgradeSeconds =
|
||||
Glean.httpsfirst.downgradeTime.testGetValue().sum / 1_000_000_000;
|
||||
ok(
|
||||
downgradeSeconds > 2 && downgradeSeconds < 30,
|
||||
`Summed downgrade time should be above 2 and below 30 seconds (is ${downgradeSeconds.toFixed(
|
||||
2
|
||||
)}s)`
|
||||
);
|
||||
is(null, Glean.httpsfirst.downgradeTimeSchemeless.testGetValue());
|
||||
});
|
||||
|
@ -153,6 +153,7 @@ async function runTest(aInput, aDesc, aExpectedScheme) {
|
||||
|
||||
add_task(async function () {
|
||||
requestLongerTimeout(10);
|
||||
Services.fog.testResetFOG();
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
@ -183,9 +184,36 @@ add_task(async function () {
|
||||
"http"
|
||||
);
|
||||
|
||||
for (const key of [
|
||||
"upgraded",
|
||||
"upgradedSchemeless",
|
||||
"downgraded",
|
||||
"downgradedSchemeless",
|
||||
"downgradedOnTimer",
|
||||
"downgradedOnTimerSchemeless",
|
||||
"downgradeTime",
|
||||
"downgradeTimeSchemeless",
|
||||
]) {
|
||||
is(
|
||||
Glean.httpsfirst[key].testGetValue(),
|
||||
null,
|
||||
`No telemetry should have been recorded yet for ${key}`
|
||||
);
|
||||
}
|
||||
|
||||
await runTest(
|
||||
"example.com",
|
||||
"Should upgrade upgradeable website without explicit scheme",
|
||||
"https"
|
||||
);
|
||||
|
||||
info("Checking expected telemetry");
|
||||
is(Glean.httpsfirst.upgraded.testGetValue(), null);
|
||||
is(Glean.httpsfirst.upgradedSchemeless.testGetValue(), 5);
|
||||
is(Glean.httpsfirst.downgraded.testGetValue(), null);
|
||||
is(Glean.httpsfirst.downgradedSchemeless.testGetValue(), null);
|
||||
is(Glean.httpsfirst.downgradedOnTimer.testGetValue(), null);
|
||||
is(Glean.httpsfirst.downgradedOnTimerSchemeless.testGetValue(), null);
|
||||
is(Glean.httpsfirst.downgradeTime.testGetValue(), null);
|
||||
is(Glean.httpsfirst.downgradeTimeSchemeless.testGetValue(), null);
|
||||
});
|
||||
|
@ -2379,8 +2379,8 @@ bool DocumentLoadListener::MaybeHandleLoadErrorWithURIFixup(nsresult aStatus) {
|
||||
// we can downgrade the scheme to HTTP again.
|
||||
bool isHTTPSFirstFixup = false;
|
||||
if (!newURI) {
|
||||
newURI = nsHTTPSOnlyUtils::PotentiallyDowngradeHttpsFirstRequest(mChannel,
|
||||
aStatus);
|
||||
newURI =
|
||||
nsHTTPSOnlyUtils::PotentiallyDowngradeHttpsFirstRequest(this, aStatus);
|
||||
isHTTPSFirstFixup = true;
|
||||
}
|
||||
|
||||
|
@ -300,6 +300,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
||||
uint32_t GetLoadType() const { return mLoadStateLoadType; }
|
||||
bool IsDownload() const { return mIsDownload; }
|
||||
bool IsLoadingJSURI() const { return mIsLoadingJSURI; }
|
||||
nsDOMNavigationTiming* GetTiming() { return mTiming; }
|
||||
|
||||
mozilla::dom::LoadingSessionHistoryInfo* GetLoadingSessionHistoryInfo() {
|
||||
return mLoadingSessionHistoryInfo.get();
|
||||
|
@ -22,6 +22,7 @@ gecko_metrics = [
|
||||
"dom/media/webrtc/metrics.yaml",
|
||||
"dom/metrics.yaml",
|
||||
"dom/performance/metrics.yaml",
|
||||
"dom/security/metrics.yaml",
|
||||
"gfx/metrics.yaml",
|
||||
"image/decoders/metrics.yaml",
|
||||
"js/xpconnect/metrics.yaml",
|
||||
|
Loading…
Reference in New Issue
Block a user