From 37a7ace2560809376296b01a421291dde26c2325 Mon Sep 17 00:00:00 2001 From: Kate McKinley Date: Tue, 9 May 2017 15:36:07 -0700 Subject: [PATCH] Bug 1359987 - Update HSTS priming telemetry r=ckerschb,francois,mayhemer p=francois Collect telemetry for all requests to get an exact percentage of requests that are subject to HSTS priming, and how many result in an HSTS Priming request being sent. Clean up telemetry to remove instances of double counting requests if a priming request was sent. HSTSPrimingListener::ReportTiming was using mCallback to calculate timing telemetry, but we were calling swap() on the nsCOMPtr. Give it an explicit argument for the callback. Add tests for telemetry values to all of the HSTS priming tests. This tests for the minimum as telemetry may be gathered on background or other requests. MozReview-Commit-ID: 5V2Nf0Ugc3r --HG-- extra : rebase_source : daa357219a77d912a78b95a703430f39d884c6ab --- dom/security/nsMixedContentBlocker.cpp | 61 ++++++------ .../hsts/browser_hsts-priming_allow_active.js | 16 ++++ .../browser_hsts-priming_allow_display.js | 16 ++++ .../hsts/browser_hsts-priming_block_active.js | 16 ++++ .../browser_hsts-priming_block_active_css.js | 16 ++++ ...ts-priming_block_active_with_redir_same.js | 16 ++++ .../browser_hsts-priming_block_display.js | 16 ++++ .../browser_hsts-priming_cache-timeout.js | 15 +++ .../browser_hsts-priming_hsts_after_mixed.js | 16 ++++ ...browser_hsts-priming_include-subdomains.js | 15 +++ .../browser_hsts-priming_no-duplicates.js | 16 ++++ .../browser_hsts-priming_no-ip-address.js | 12 +++ ...wser_hsts-priming_no-non-standard-ports.js | 17 +++- .../test/hsts/browser_hsts-priming_timeout.js | 15 +++ dom/security/test/hsts/head.js | 92 +++++++++++++++++++ ipc/glue/BackgroundUtils.cpp | 9 +- netwerk/base/LoadInfo.cpp | 44 ++++++++- netwerk/base/LoadInfo.h | 6 +- netwerk/base/nsILoadInfo.idl | 10 ++ netwerk/base/nsNetUtil.cpp | 23 +++++ netwerk/ipc/NeckoChannelParams.ipdlh | 2 + netwerk/protocol/http/HSTSPrimerListener.cpp | 41 ++++++--- netwerk/protocol/http/HSTSPrimerListener.h | 29 +++++- netwerk/protocol/http/nsHttpChannel.cpp | 58 ++++++++++-- toolkit/components/telemetry/Histograms.json | 33 ++++--- 25 files changed, 539 insertions(+), 71 deletions(-) diff --git a/dom/security/nsMixedContentBlocker.cpp b/dom/security/nsMixedContentBlocker.cpp index 746f65cac6dd..ba61c7f79378 100644 --- a/dom/security/nsMixedContentBlocker.cpp +++ b/dom/security/nsMixedContentBlocker.cpp @@ -90,6 +90,29 @@ IsEligibleForHSTSPriming(nsIURI* aContentLocation) { return (PR_StringToNetAddr(hostname.get(), &hostAddr) != PR_SUCCESS); } +enum MixedContentHSTSState { + MCB_HSTS_PASSIVE_NO_HSTS = 0, + MCB_HSTS_PASSIVE_WITH_HSTS = 1, + MCB_HSTS_ACTIVE_NO_HSTS = 2, + MCB_HSTS_ACTIVE_WITH_HSTS = 3 +}; + +// Similar to the existing mixed-content HSTS, except MCB_HSTS_*_NO_HSTS is +// broken into two distinct states, indicating whether we plan to send a priming +// request or not. If we decided not go send a priming request, it could be +// because it is a type we do not support, or because we cached a previous +// negative response. +enum MixedContentHSTSPrimingState { + eMCB_HSTS_PASSIVE_WITH_HSTS = 0, + eMCB_HSTS_ACTIVE_WITH_HSTS = 1, + eMCB_HSTS_PASSIVE_NO_PRIMING = 2, + eMCB_HSTS_PASSIVE_DO_PRIMING = 3, + eMCB_HSTS_ACTIVE_NO_PRIMING = 4, + eMCB_HSTS_ACTIVE_DO_PRIMING = 5, + eMCB_HSTS_PASSIVE_UPGRADE = 6, + eMCB_HSTS_ACTIVE_UPGRADE = 7, +}; + // Fired at the document that attempted to load mixed content. The UI could // handle this event, for example, by displaying an info bar that offers the // choice to reload the page with mixed content permitted. @@ -892,6 +915,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, originAttributes = aRequestPrincipal->OriginAttributesRef(); } + bool active = (classification == eMixedScript); bool doHSTSPriming = false; if (IsEligibleForHSTSPriming(aContentLocation)) { bool hsts = false; @@ -905,6 +929,9 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, if (hsts && sUseHSTS) { // assume we will be upgraded later + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_2, + (active) ? MixedContentHSTSPrimingState::eMCB_HSTS_ACTIVE_UPGRADE + : MixedContentHSTSPrimingState::eMCB_HSTS_PASSIVE_UPGRADE); *aDecision = ACCEPT; return NS_OK; } @@ -932,7 +959,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, // // We do not count requests aHadInsecureImageRedirect=true, since these are // just an artifact of the image caching system. - bool active = (classification == eMixedScript); if (!aHadInsecureImageRedirect) { if (XRE_IsParentProcess()) { AccumulateMixedContentHSTS(innerContentLocation, active, doHSTSPriming, @@ -1103,27 +1129,6 @@ nsMixedContentBlocker::ShouldProcess(uint32_t aContentType, aDecision); } -enum MixedContentHSTSState { - MCB_HSTS_PASSIVE_NO_HSTS = 0, - MCB_HSTS_PASSIVE_WITH_HSTS = 1, - MCB_HSTS_ACTIVE_NO_HSTS = 2, - MCB_HSTS_ACTIVE_WITH_HSTS = 3 -}; - -// Similar to the existing mixed-content HSTS, except MCB_HSTS_*_NO_HSTS is -// broken into two distinct states, indicating whether we plan to send a priming -// request or not. If we decided not go send a priming request, it could be -// because it is a type we do not support, or because we cached a previous -// negative response. -enum MixedContentHSTSPrimingState { - eMCB_HSTS_PASSIVE_WITH_HSTS = 0, - eMCB_HSTS_ACTIVE_WITH_HSTS = 1, - eMCB_HSTS_PASSIVE_NO_PRIMING = 2, - eMCB_HSTS_PASSIVE_DO_PRIMING = 3, - eMCB_HSTS_ACTIVE_NO_PRIMING = 4, - eMCB_HSTS_ACTIVE_DO_PRIMING = 5 -}; - // Record information on when HSTS would have made mixed content not mixed // content (regardless of whether it was actually blocked) void @@ -1158,17 +1163,17 @@ nsMixedContentBlocker::AccumulateMixedContentHSTS( Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS, MCB_HSTS_PASSIVE_NO_HSTS); if (aHasHSTSPriming) { - Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING, + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_2, eMCB_HSTS_PASSIVE_DO_PRIMING); } else { - Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING, + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_2, eMCB_HSTS_PASSIVE_NO_PRIMING); } } else { Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS, MCB_HSTS_PASSIVE_WITH_HSTS); - Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING, + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_2, eMCB_HSTS_PASSIVE_WITH_HSTS); } } else { @@ -1176,17 +1181,17 @@ nsMixedContentBlocker::AccumulateMixedContentHSTS( Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS, MCB_HSTS_ACTIVE_NO_HSTS); if (aHasHSTSPriming) { - Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING, + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_2, eMCB_HSTS_ACTIVE_DO_PRIMING); } else { - Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING, + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_2, eMCB_HSTS_ACTIVE_NO_PRIMING); } } else { Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS, MCB_HSTS_ACTIVE_WITH_HSTS); - Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING, + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_2, eMCB_HSTS_ACTIVE_WITH_HSTS); } } diff --git a/dom/security/test/hsts/browser_hsts-priming_allow_active.js b/dom/security/test/hsts/browser_hsts-priming_allow_active.js index 3360d146d87e..4e5e2d9acfc2 100644 --- a/dom/security/test/hsts/browser_hsts-priming_allow_active.js +++ b/dom/security/test/hsts/browser_hsts-priming_allow_active.js @@ -5,6 +5,19 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 6, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -15,10 +28,13 @@ add_task(function*() { let which = "allow_active"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_allow_display.js b/dom/security/test/hsts/browser_hsts-priming_allow_display.js index 9308043ea99c..0d0990620911 100644 --- a/dom/security/test/hsts/browser_hsts-priming_allow_display.js +++ b/dom/security/test/hsts/browser_hsts-priming_allow_display.js @@ -5,6 +5,19 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 6, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -15,10 +28,13 @@ add_task(function*() { let which = "allow_display"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_block_active.js b/dom/security/test/hsts/browser_hsts-priming_block_active.js index 3ce07ae5f07a..a48a7646cd06 100644 --- a/dom/security/test/hsts/browser_hsts-priming_block_active.js +++ b/dom/security/test/hsts/browser_hsts-priming_block_active.js @@ -5,6 +5,19 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 6, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -15,10 +28,13 @@ add_task(function*() { let which = "block_active"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_block_active_css.js b/dom/security/test/hsts/browser_hsts-priming_block_active_css.js index fbd888b2e03e..f187ee85f07d 100644 --- a/dom/security/test/hsts/browser_hsts-priming_block_active_css.js +++ b/dom/security/test/hsts/browser_hsts-priming_block_active_css.js @@ -5,6 +5,19 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 6, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -15,10 +28,13 @@ add_task(function*() { let which = "block_active_css"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_block_active_with_redir_same.js b/dom/security/test/hsts/browser_hsts-priming_block_active_with_redir_same.js index 54aaa93dde8c..af24caee9716 100644 --- a/dom/security/test/hsts/browser_hsts-priming_block_active_with_redir_same.js +++ b/dom/security/test/hsts/browser_hsts-priming_block_active_with_redir_same.js @@ -5,6 +5,19 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 6, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -15,10 +28,13 @@ add_task(function*() { let which = "block_active_with_redir_same"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_block_display.js b/dom/security/test/hsts/browser_hsts-priming_block_display.js index d316c2e2ac96..02763786642d 100644 --- a/dom/security/test/hsts/browser_hsts-priming_block_display.js +++ b/dom/security/test/hsts/browser_hsts-priming_block_display.js @@ -5,6 +5,19 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 6, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -15,10 +28,13 @@ add_task(function*() { let which = "block_display"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_cache-timeout.js b/dom/security/test/hsts/browser_hsts-priming_cache-timeout.js index 5416a71d275c..350ea435ff40 100644 --- a/dom/security/test/hsts/browser_hsts-priming_cache-timeout.js +++ b/dom/security/test/hsts/browser_hsts-priming_cache-timeout.js @@ -5,6 +5,18 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 2, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 4, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -14,6 +26,7 @@ add_task(function*() { let which = "block_display"; SetupPrefTestEnvironment(which, [["security.mixed_content.hsts_priming_cache_timeout", 1]]); + clear_hists(expected_telemetry); yield execute_test("no-ssl", test_settings[which].mimetype); @@ -32,5 +45,7 @@ add_task(function*() { is(test_settings[which].priming["no-ssl"], true, "Correctly send a priming request after expiration."); + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_hsts_after_mixed.js b/dom/security/test/hsts/browser_hsts-priming_hsts_after_mixed.js index 96e9b66567b8..b5f65451a5ed 100644 --- a/dom/security/test/hsts/browser_hsts-priming_hsts_after_mixed.js +++ b/dom/security/test/hsts/browser_hsts-priming_hsts_after_mixed.js @@ -5,6 +5,19 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 6, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -15,10 +28,13 @@ add_task(function*() { let which = "hsts_after_mixed"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_include-subdomains.js b/dom/security/test/hsts/browser_hsts-priming_include-subdomains.js index 1912fff2cc34..3f73571d784f 100644 --- a/dom/security/test/hsts/browser_hsts-priming_include-subdomains.js +++ b/dom/security/test/hsts/browser_hsts-priming_include-subdomains.js @@ -10,6 +10,18 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 2, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 4, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -27,6 +39,7 @@ add_task(function*() { let which = "block_active"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); yield execute_test("top-level", test_settings[which].mimetype); @@ -35,5 +48,7 @@ add_task(function*() { ok("prime-hsts" in test_settings[which].priming, "HSTS priming on a subdomain when top-level does not includeSubDomains"); + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_no-duplicates.js b/dom/security/test/hsts/browser_hsts-priming_no-duplicates.js index a56752d3e51f..b41b2b277bfa 100644 --- a/dom/security/test/hsts/browser_hsts-priming_no-duplicates.js +++ b/dom/security/test/hsts/browser_hsts-priming_no-duplicates.js @@ -5,6 +5,19 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 8, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -14,6 +27,7 @@ add_task(function*() { let which = "block_display"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); @@ -24,5 +38,7 @@ add_task(function*() { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_no-ip-address.js b/dom/security/test/hsts/browser_hsts-priming_no-ip-address.js index d70344e5ff6e..71f8b62f8a41 100644 --- a/dom/security/test/hsts/browser_hsts-priming_no-ip-address.js +++ b/dom/security/test/hsts/browser_hsts-priming_no-ip-address.js @@ -6,6 +6,15 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 0, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 1, + }, + "keyed-histograms": { + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -23,8 +32,11 @@ add_task(function*() { let which = "block_active"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); yield execute_test("localhost-ip", test_settings[which].mimetype); + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_no-non-standard-ports.js b/dom/security/test/hsts/browser_hsts-priming_no-non-standard-ports.js index 2525f8e76674..e3c8360952bb 100644 --- a/dom/security/test/hsts/browser_hsts-priming_no-non-standard-ports.js +++ b/dom/security/test/hsts/browser_hsts-priming_no-non-standard-ports.js @@ -6,6 +6,18 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 1, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 3, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -14,7 +26,7 @@ add_task(function*() { // add the top-level server test_servers['non-standard-port'] = { - host: 'example.com:1234', + host: 'test1.example.com:1234', response: true, id: 'non-standard-port', }; @@ -23,6 +35,7 @@ add_task(function*() { let which = "block_active"; SetupPrefTestEnvironment(which); + clear_hists(expected_telemetry); yield execute_test("non-standard-port", test_settings[which].mimetype); @@ -30,5 +43,7 @@ add_task(function*() { ok("prime-hsts" in test_settings[which_test].priming, "Sent priming request on standard port after non-standard was not primed"); + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/browser_hsts-priming_timeout.js b/dom/security/test/hsts/browser_hsts-priming_timeout.js index b4c54e854194..5e8d9a7cd054 100644 --- a/dom/security/test/hsts/browser_hsts-priming_timeout.js +++ b/dom/security/test/hsts/browser_hsts-priming_timeout.js @@ -5,6 +5,18 @@ */ 'use strict'; +var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 3, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": 3, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "failure": 3, + }, + } +}; + //jscs:disable add_task(function*() { //jscs:enable @@ -15,10 +27,13 @@ add_task(function*() { SetupPrefTestEnvironment(which, [["security.mixed_content.hsts_priming_request_timeout", 1000]]); + clear_hists(expected_telemetry); for (let server of Object.keys(test_servers)) { yield execute_test(server, test_settings[which].mimetype); } + test_telemetry(expected_telemetry); + SpecialPowers.popPrefEnv(); }); diff --git a/dom/security/test/hsts/head.js b/dom/security/test/hsts/head.js index 23745b36de03..0bfb84148ee7 100644 --- a/dom/security/test/hsts/head.js +++ b/dom/security/test/hsts/head.js @@ -377,12 +377,16 @@ function clear_sts_data() { } } +var oldCanRecord = Services.telemetry.canRecordExtended; + function do_cleanup() { clear_sts_data(); Services.obs.removeObserver(Observer, "console-api-log-event"); Services.obs.removeObserver(Observer, "http-on-examine-response"); + Services.telemetry.canRecordExtended = oldCanRecord; + Observer.cleanup(); } @@ -404,6 +408,7 @@ function SetupPrefTestEnvironment(which, additional_prefs) { settings.use_hsts], ["security.mixed_content.send_hsts_priming", settings.send_hsts_priming], + ["toolkit.telemetry.enabled", true], ]; if (additional_prefs) { @@ -412,6 +417,8 @@ function SetupPrefTestEnvironment(which, additional_prefs) { } } + Services.telemetry.canRecordExtended = true; + SpecialPowers.pushPrefEnv({'set': prefs}); } @@ -433,3 +440,88 @@ async function execute_test(test, mimetype) { await BrowserTestUtils.withNewTab(src, () => {}); } + +/* Expected should look something like this: + * The numbers are the sum of all telemetry values. + var expected_telemetry = { + "histograms": { + "MIXED_CONTENT_HSTS_PRIMING_RESULT": 6, + "HSTS_PRIMING_REQUESTS": 10, + }, + "keyed-histograms": { + "HSTS_PRIMING_REQUEST_DURATION": { + "success": 1, + "failure": 2, + }, + } + }; + */ +function test_telemetry(expected) { + for (let key in expected['histograms']) { + let hs = undefined; + try { + let hist = Services.telemetry.getHistogramById(key); + hs = hist.snapshot(); + hist.clear(); + } catch(e) { + ok(false, "Caught exception trying to get histogram for key " + key + ":" + e); + continue; + } + + if (!hs) { + ok(false, "No histogram found for key " + key); + continue; + } + + // there may have been other background requests processed + ok(hs.counts.reduce(sum) >= expected['histograms'][key], "Histogram counts match expected, got " + hs.counts.reduce(sum) + ", expected at least " + expected['histograms'][key]); + } + + for (let key in expected['keyed-histograms']) { + let hs = undefined; + try { + let hist = Services.telemetry.getKeyedHistogramById(key); + hs = hist.snapshot(); + hist.clear(); + } catch(e) { + ok(false, "Caught exception trying to get histogram for key " + key + " :" + e); + continue; + } + + if (!hs) { + ok(false, "No keyed histogram found for key " + key); + continue; + } + + for (let hist_key in expected['keyed-histograms'][key]) { + ok(hist_key in hs, "Keyed histogram exists with key"); + if (hist_key in hs) { + ok(hs[hist_key].counts.reduce(sum) >= expected['keyed-histograms'][key][hist_key], "Keyed histogram counts match expected got " + hs[hist_key].counts.reduce(sum) + ", expected at least " + expected['keyed-histograms'][key][hist_key]) + } + } + } +} + +function sum(a, b) { + return a+b; +} + +function clear_hists(hists) { + for (let key in hists['histograms']) { + try { + let hist = Services.telemetry.getHistogramById(key); + hist.clear(); + } catch(e) { + continue; + } + } + + for (let key in hists['keyed-histograms']) { + try { + let hist = Services.telemetry.getKeyedHistogramById(key); + hist.clear(); + } catch(e) { + continue; + } + } +} diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index b8f0e7bb5a42..5ab37cce6fb2 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -389,7 +389,10 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, aLoadInfo->GetForcePreflight(), aLoadInfo->GetIsPreflight(), aLoadInfo->GetForceHSTSPriming(), - aLoadInfo->GetMixedContentWouldBlock()); + aLoadInfo->GetMixedContentWouldBlock(), + aLoadInfo->GetIsHSTSPriming(), + aLoadInfo->GetIsHSTSPrimingUpgrade() + ); return NS_OK; } @@ -474,7 +477,9 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, loadInfoArgs.forcePreflight(), loadInfoArgs.isPreflight(), loadInfoArgs.forceHSTSPriming(), - loadInfoArgs.mixedContentWouldBlock() + loadInfoArgs.mixedContentWouldBlock(), + loadInfoArgs.isHSTSPriming(), + loadInfoArgs.isHSTSPrimingUpgrade() ); loadInfo.forget(outLoadInfo); diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index d6d233c19b50..99d9e7198f46 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -58,6 +58,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mIsPreflight(false) , mForceHSTSPriming(false) , mMixedContentWouldBlock(false) + , mIsHSTSPriming(false) + , mIsHSTSPrimingUpgrade(false) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); @@ -231,6 +233,8 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, , mIsPreflight(false) , mForceHSTSPriming(false) , mMixedContentWouldBlock(false) + , mIsHSTSPriming(false) + , mIsHSTSPrimingUpgrade(false) { // Top-level loads are never third-party // Grab the information we can out of the window. @@ -294,6 +298,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) , mIsPreflight(rhs.mIsPreflight) , mForceHSTSPriming(rhs.mForceHSTSPriming) , mMixedContentWouldBlock(rhs.mMixedContentWouldBlock) + , mIsHSTSPriming(rhs.mIsHSTSPriming) + , mIsHSTSPrimingUpgrade(rhs.mIsHSTSPrimingUpgrade) { } @@ -322,7 +328,9 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, bool aForcePreflight, bool aIsPreflight, bool aForceHSTSPriming, - bool aMixedContentWouldBlock) + bool aMixedContentWouldBlock, + bool aIsHSTSPriming, + bool aIsHSTSPrimingUpgrade) : mLoadingPrincipal(aLoadingPrincipal) , mTriggeringPrincipal(aTriggeringPrincipal) , mPrincipalToInherit(aPrincipalToInherit) @@ -346,6 +354,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mIsPreflight(aIsPreflight) , mForceHSTSPriming (aForceHSTSPriming) , mMixedContentWouldBlock(aMixedContentWouldBlock) + , mIsHSTSPriming(aIsHSTSPriming) + , mIsHSTSPrimingUpgrade(aIsHSTSPrimingUpgrade) { // Only top level TYPE_DOCUMENT loads can have a null loadingPrincipal MOZ_ASSERT(mLoadingPrincipal || aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT); @@ -933,6 +943,38 @@ LoadInfo::ClearHSTSPriming() mMixedContentWouldBlock = false; } +NS_IMETHODIMP +LoadInfo::SetIsHSTSPriming(bool aIsHSTSPriming) +{ + MOZ_ASSERT(aIsHSTSPriming); + mIsHSTSPriming = aIsHSTSPriming; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetIsHSTSPriming(bool* aIsHSTSPriming) +{ + MOZ_ASSERT(aIsHSTSPriming); + *aIsHSTSPriming = mIsHSTSPriming; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::SetIsHSTSPrimingUpgrade(bool aIsHSTSPrimingUpgrade) +{ + MOZ_ASSERT(aIsHSTSPrimingUpgrade); + mIsHSTSPrimingUpgrade = aIsHSTSPrimingUpgrade; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetIsHSTSPrimingUpgrade(bool* aIsHSTSPrimingUpgrade) +{ + MOZ_ASSERT(aIsHSTSPrimingUpgrade); + *aIsHSTSPrimingUpgrade = mIsHSTSPrimingUpgrade; + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetTainting(uint32_t* aTaintingOut) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index f10b5e04a7a5..3cd71b734f78 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -115,7 +115,9 @@ private: bool aForcePreflight, bool aIsPreflight, bool aForceHSTSPriming, - bool aMixedContentWouldBlock); + bool aMixedContentWouldBlock, + bool aIsHSTSPriming, + bool aIsHSTSPrimingUpgrade); LoadInfo(const LoadInfo& rhs); NS_IMETHOD GetRedirects(JSContext* aCx, JS::MutableHandle aRedirects, @@ -165,6 +167,8 @@ private: bool mForceHSTSPriming : 1; bool mMixedContentWouldBlock : 1; + bool mIsHSTSPriming: 1; + bool mIsHSTSPrimingUpgrade: 1; }; } // namespace net diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 540520e8820e..117fe506deb9 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -675,6 +675,16 @@ interface nsILoadInfo : nsISupports */ [noscript, infallible] readonly attribute boolean mixedContentWouldBlock; + /** + * True if this load is an HSTS priming request. + */ + [noscript, infallible] attribute boolean isHSTSPriming; + + /** + * True if this load was upgraded from HSTS priming + */ + [noscript, infallible] attribute boolean isHSTSPrimingUpgrade; + /** * Mark this LoadInfo as needing HSTS Priming * diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp index 15b5ddf52a18..5000f073f197 100644 --- a/netwerk/base/nsNetUtil.cpp +++ b/netwerk/base/nsNetUtil.cpp @@ -2569,6 +2569,14 @@ NS_ShouldSecureUpgrade(nsIURI* aURI, aShouldUpgrade = true; return NS_OK; } + + if (aLoadInfo->GetForceHSTSPriming()) { + // don't log requests which might be upgraded due to HSTS Priming + // they get logged in nsHttpChannel::OnHSTSPrimingSucceeded or + // nsHttpChannel::OnHSTSPrimingFailed if the load is allowed to proceed. + aShouldUpgrade = false; + return NS_OK; + } } // enforce Strict-Transport-Security @@ -2598,6 +2606,21 @@ NS_ShouldSecureUpgrade(nsIURI* aURI, Telemetry::Accumulate(Telemetry::HTTP_SCHEME_UPGRADE, 1); } } else { + if (aLoadInfo) { + if (aLoadInfo->GetIsHSTSPriming()) { + // don't log HSTS priming requests + aShouldUpgrade = false; + return NS_OK; + } + + if (aLoadInfo->GetIsHSTSPrimingUpgrade()) { + // if the upgrade occured due to HSTS priming, it was logged in + // nsHttpChannel::OnHSTSPrimingSucceeded before redirect + aShouldUpgrade = false; + return NS_OK; + } + } + Telemetry::Accumulate(Telemetry::HTTP_SCHEME_UPGRADE, 0); } aShouldUpgrade = false; diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index e2debc306ee5..874c248a32ea 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -63,6 +63,8 @@ struct LoadInfoArgs bool isPreflight; bool forceHSTSPriming; bool mixedContentWouldBlock; + bool isHSTSPriming; + bool isHSTSPrimingUpgrade; }; /** diff --git a/netwerk/protocol/http/HSTSPrimerListener.cpp b/netwerk/protocol/http/HSTSPrimerListener.cpp index 3d7c81ba0fb0..d05d55a62503 100644 --- a/netwerk/protocol/http/HSTSPrimerListener.cpp +++ b/netwerk/protocol/http/HSTSPrimerListener.cpp @@ -51,21 +51,24 @@ HSTSPrimingListener::GetInterface(const nsIID & aIID, void **aResult) } void -HSTSPrimingListener::ReportTiming(nsresult aResult) +HSTSPrimingListener::ReportTiming(nsIHstsPrimingCallback* aCallback, nsresult aResult) { nsCOMPtr timingChannel = - do_QueryInterface(mCallback); - if (timingChannel) { - TimeStamp channelCreationTime; - nsresult rv = timingChannel->GetChannelCreation(&channelCreationTime); - if (NS_SUCCEEDED(rv) && !channelCreationTime.IsNull()) { - PRUint32 interval = - (PRUint32) (TimeStamp::Now() - channelCreationTime).ToMilliseconds(); - Telemetry::Accumulate(Telemetry::HSTS_PRIMING_REQUEST_DURATION, - (NS_SUCCEEDED(aResult)) ? NS_LITERAL_CSTRING("success") - : NS_LITERAL_CSTRING("failure"), - interval); - } + do_QueryInterface(aCallback); + if (!timingChannel) { + LOG(("HSTS priming: mCallback is not an nsITimedChannel!")); + return; + } + + TimeStamp channelCreationTime; + nsresult rv = timingChannel->GetChannelCreation(&channelCreationTime); + if (NS_SUCCEEDED(rv) && !channelCreationTime.IsNull()) { + PRUint32 interval = + (PRUint32) (TimeStamp::Now() - channelCreationTime).ToMilliseconds(); + Telemetry::Accumulate(Telemetry::HSTS_PRIMING_REQUEST_DURATION, + (NS_SUCCEEDED(aResult)) ? NS_LITERAL_CSTRING("success") + : NS_LITERAL_CSTRING("failure"), + interval); } } @@ -88,7 +91,7 @@ HSTSPrimingListener::OnStartRequest(nsIRequest *aRequest, } nsresult primingResult = CheckHSTSPrimingRequestStatus(aRequest); - ReportTiming(primingResult); + ReportTiming(callback, primingResult); if (NS_FAILED(primingResult)) { LOG(("HSTS Priming Failed (request was not approved)")); @@ -192,7 +195,7 @@ HSTSPrimingListener::Notify(nsITimer* timer) return NS_OK; } - ReportTiming(NS_ERROR_HSTS_PRIMING_TIMEOUT); + ReportTiming(callback, NS_ERROR_HSTS_PRIMING_TIMEOUT); if (mPrimingChannel) { rv = mPrimingChannel->Cancel(NS_ERROR_HSTS_PRIMING_TIMEOUT); @@ -237,12 +240,16 @@ HSTSPrimingListener::StartHSTSPriming(nsIChannel* aRequestChannel, if (hsts) { // already saw this host and will upgrade if allowed by preferences + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_REQUESTS, + HSTSPrimingRequest::eHSTS_PRIMING_REQUEST_CACHED_HSTS); return aCallback->OnHSTSPrimingSucceeded(true); } if (cached) { // there is a non-expired entry in the cache that doesn't allow us to // upgrade, so go ahead and fail early. + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_REQUESTS, + HSTSPrimingRequest::eHSTS_PRIMING_REQUEST_CACHED_NO_HSTS); return aCallback->OnHSTSPrimingFailed(NS_ERROR_CONTENT_BLOCKED, true); } @@ -257,6 +264,7 @@ HSTSPrimingListener::StartHSTSPriming(nsIChannel* aRequestChannel, nsCOMPtr loadInfo = static_cast (originalLoadInfo.get())->CloneForNewRequest(); + loadInfo->SetIsHSTSPriming(true); // the LoadInfo must have a security flag set in order to pass through priming // if none of these security flags are set, go ahead and fail now instead of @@ -370,6 +378,9 @@ HSTSPrimingListener::StartHSTSPriming(nsIChannel* aRequestChannel, listener->mHSTSPrimingTimer.swap(timer); + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_REQUESTS, + HSTSPrimingRequest::eHSTS_PRIMING_REQUEST_SENT); + return NS_OK; } diff --git a/netwerk/protocol/http/HSTSPrimerListener.h b/netwerk/protocol/http/HSTSPrimerListener.h index 6a72938cd164..54ccb9da9230 100644 --- a/netwerk/protocol/http/HSTSPrimerListener.h +++ b/netwerk/protocol/http/HSTSPrimerListener.h @@ -26,6 +26,31 @@ namespace net { class HttpChannelParent; class nsHttpChannel; +/* + * How often do we send an HSTS priming request (over all requests) + */ +enum HSTSPrimingRequest { + // No HSTS priming request. The request is not mixed-content, or we have + // already cached the result before nsMixedContentBlocker::ShouldLoad + eHSTS_PRIMING_NO_REQUEST = 0, + // Sent an HSTS priming request + eHSTS_PRIMING_REQUEST_SENT = 1, + // Channel marked for priming, but already had a cached result + eHSTS_PRIMING_REQUEST_CACHED_HSTS = 2, + // Channel marked for priming, but already had a cached result + eHSTS_PRIMING_REQUEST_CACHED_NO_HSTS = 3, + // An error occured setting up the the priming request channel. If the + // priming channel failed in OnstopRequest, there is no HSTS, or the + // channel is redirected, that is recorded by + // MIXED_CONTENT_HSTS_PRIMING_RESULT. + eHSTS_PRIMING_REQUEST_ERROR = 4, + // The channel had no load info, so is ineligible for priming + eHSTS_PRIMING_REQUEST_NO_LOAD_INFO = 5, + // The request was marked for HSTS priming, but was upgraded by + // NS_ShouldSecureUpgrade before HSTS priming was sent. + eHSTS_PRIMING_REQUEST_ALREADY_UPGRADED = 6, +}; + /* * How often do we get back an HSTS priming result which upgrades the connection to HTTPS? */ @@ -56,7 +81,7 @@ enum HSTSPrimingResult { eHSTS_PRIMING_TIMEOUT_BLOCK = 9, // The HSTS Priming request timed out, and the load is allowed by // mixed-content - eHSTS_PRIMING_TIMEOUT_ACCEPT = 10 + eHSTS_PRIMING_TIMEOUT_ACCEPT = 10, }; ////////////////////////////////////////////////////////////////////////// @@ -103,7 +128,7 @@ private: nsresult CheckHSTSPrimingRequestStatus(nsIRequest* aRequest); // send telemetry about how long HSTS priming requests take - void ReportTiming(nsresult aResult); + void ReportTiming(nsIHstsPrimingCallback* aCallback, nsresult aResult); /** * the nsIHttpChannel to notify with the result of HSTS priming. diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 34fb864f1367..66bc215fd9c4 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -483,6 +483,11 @@ nsresult nsHttpChannel::TryHSTSPriming() { if (mLoadInfo) { + if (mLoadInfo->GetIsHSTSPriming()) { + // shortcut priming requests so they don't get counted + return ContinueConnect(); + } + // HSTS priming requires the LoadInfo provided with AsyncOpen2 bool requireHSTSPriming = mLoadInfo->GetForceHSTSPriming(); @@ -498,18 +503,38 @@ nsHttpChannel::TryHSTSPriming() if (NS_FAILED(rv)) { CloseCacheEntry(false); + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_REQUESTS, + HSTSPrimingRequest::eHSTS_PRIMING_REQUEST_ERROR); return rv; } return NS_OK; } - // The request was already upgraded, for example by - // upgrade-insecure-requests or a prior successful priming request - Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT, - HSTSPrimingResult::eHSTS_PRIMING_ALREADY_UPGRADED); + if (!mLoadInfo->GetIsHSTSPrimingUpgrade()) { + // The request was already upgraded, for example by a prior + // successful priming request + LOG(("HSTS Priming: request already upgraded")); + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT, + HSTSPrimingResult::eHSTS_PRIMING_ALREADY_UPGRADED); + + // No HSTS Priming request was sent. + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_REQUESTS, + HSTSPrimingRequest::eHSTS_PRIMING_REQUEST_ALREADY_UPGRADED); + } + mLoadInfo->ClearHSTSPriming(); + return ContinueConnect(); } + + if (!mLoadInfo->GetIsHSTSPrimingUpgrade()) { + // No HSTS Priming request was sent, and we didn't already record this request + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_REQUESTS, + HSTSPrimingRequest::eHSTS_PRIMING_NO_REQUEST); + } + } else { + Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_REQUESTS, + HSTSPrimingRequest::eHSTS_PRIMING_REQUEST_NO_LOAD_INFO); } return ContinueConnect(); @@ -8605,6 +8630,14 @@ nsHttpChannel::OnPreflightFailed(nsresult aError) nsresult nsHttpChannel::OnHSTSPrimingSucceeded(bool aCached) { + // If "security.mixed_content.use_hsts" is false, record the result of + // HSTS priming and block or proceed with the load as required by + // mixed-content blocking + bool wouldBlock = mLoadInfo->GetMixedContentWouldBlock(); + // Clear out the HSTS priming flags on the LoadInfo to simplify the logic in + // TryHSTSPriming() + mLoadInfo->ClearHSTSPriming(); + if (nsMixedContentBlocker::sUseHSTS) { // redirect the channel to HTTPS if the pref // "security.mixed_content.use_hsts" is true @@ -8612,14 +8645,12 @@ nsHttpChannel::OnHSTSPrimingSucceeded(bool aCached) Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT, (aCached) ? HSTSPrimingResult::eHSTS_PRIMING_CACHED_DO_UPGRADE : HSTSPrimingResult::eHSTS_PRIMING_SUCCEEDED); + // we have to record this upgrade here + Telemetry::Accumulate(Telemetry::HTTP_SCHEME_UPGRADE, 3); + mLoadInfo->SetIsHSTSPrimingUpgrade(true); return AsyncCall(&nsHttpChannel::HandleAsyncRedirectChannelToHttps); } - // If "security.mixed_content.use_hsts" is false, record the result of - // HSTS priming and block or proceed with the load as required by - // mixed-content blocking - bool wouldBlock = mLoadInfo->GetMixedContentWouldBlock(); - // preserve the mixed-content-before-hsts order and block if required if (wouldBlock) { LOG(("HSTS Priming succeeded, blocking for mixed-content [this=%p]", @@ -8634,6 +8665,9 @@ nsHttpChannel::OnHSTSPrimingSucceeded(bool aCached) Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT, HSTSPrimingResult::eHSTS_PRIMING_SUCCEEDED_HTTP); + // log HTTP_SCHEME_UPGRADE telemetry + Telemetry::Accumulate(Telemetry::HTTP_SCHEME_UPGRADE, 0); + nsresult rv = ContinueConnect(); if (NS_FAILED(rv)) { CloseCacheEntry(false); @@ -8651,6 +8685,9 @@ nsresult nsHttpChannel::OnHSTSPrimingFailed(nsresult aError, bool aCached) { bool wouldBlock = mLoadInfo->GetMixedContentWouldBlock(); + // Clear out the HSTS priming flags on the LoadInfo to simplify the logic in + // TryHSTSPriming() + mLoadInfo->ClearHSTSPriming(); LOG(("HSTS Priming Failed [this=%p], %s the load", this, (wouldBlock) ? "blocking" : "allowing")); @@ -8692,6 +8729,9 @@ nsHttpChannel::OnHSTSPrimingFailed(nsresult aError, bool aCached) return AsyncAbort(aError); } + // log HTTP_SCHEME_UPGRADE telemetry + Telemetry::Accumulate(Telemetry::HTTP_SCHEME_UPGRADE, 0); + // we can continue the load and the UI has been updated as mixed content rv = ContinueConnect(); if (NS_FAILED(rv)) { diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index db53f28b1ce8..c421b137211a 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -10107,35 +10107,44 @@ }, "MIXED_CONTENT_HSTS": { "record_in_processes": ["main", "content"], - "alert_emails": ["seceng@mozilla.org"], + "alert_emails": ["seceng-telemetry@mozilla.com"], "expires_in_version": "never", "kind": "enumerated", "n_values": 10, "description": "How often would blocked mixed content be allowed if HSTS upgrades were allowed? 0=display/no-HSTS, 1=display/HSTS, 2=active/no-HSTS, 3=active/HSTS" }, - "MIXED_CONTENT_HSTS_PRIMING": { - "record_in_processes": ["main", "content"], - "alert_emails": ["seceng@mozilla.org"], - "bug_numbers": [1246540], + "MIXED_CONTENT_HSTS_PRIMING_2": { + "record_in_processes": [ "main" ], + "alert_emails": ["seceng-telemetry@mozilla.com"], + "bug_numbers": [1359987], "expires_in_version": "60", "kind": "enumerated", "n_values": 16, - "description": "How often would blocked mixed content be allowed if HSTS upgrades were allowed, including how often would we send an HSTS priming request? 0=display/no-HSTS, 1=display/HSTS, 2=active/no-HSTS, 3=active/HSTS, 4=display/no-HSTS-priming, 5=display/do-HSTS-priming, 6=active/no-HSTS-priming, 7=active/do-HSTS-priming" + "description": "How often would blocked mixed content be allowed if HSTS upgrades were allowed, including how often would we send an HSTS priming request? 0=passive/HSTS, 1=active/HSTS, 2=passive/no priming, 3=passive/priming, 4=active/no priming, 5=active/priming, 6=passive/will HSTS upgrade, 7=active/will HSTS upgrade" }, "MIXED_CONTENT_HSTS_PRIMING_RESULT": { - "record_in_processes": ["main", "content"], - "alert_emails": ["seceng@mozilla.org"], + "record_in_processes": [ "main" ], + "alert_emails": ["seceng-telemetry@mozilla.com"], "bug_numbers": [1246540], "expires_in_version": "60", "kind": "enumerated", "n_values": 16, "description": "How often do we get back an HSTS priming result which upgrades the connection to HTTPS? 0=cached (no upgrade), 1=cached (do upgrade), 2=cached (blocked), 3=already upgraded, 4=priming succeeded, 5=priming succeeded (block due to pref), 6=priming succeeded (no upgrade due to pref), 7=priming failed (block), 8=priming failed (accept), 9=timeout (block), 10=timeout (accept)" }, + "MIXED_CONTENT_HSTS_PRIMING_REQUESTS": { + "record_in_processes": [ "main" ], + "alert_emails": ["seceng-telemetry@mozilla.com"], + "bug_numbers": [1359987], + "expires_in_version": "62", + "kind": "enumerated", + "n_values": 10, + "description": "How often does a request result in HSTS priming? (0=Sent HSTS priming, 1=No priming, 2=Priming skipped due to cached HSTS, 3=Priming skipped due to cached NO HSTS, 4=Priming failed (request error), 5=Priming skipped (missing load info), 6=Priming skipped (already upgraded)" + }, "HSTS_PRIMING_REQUEST_DURATION": { - "record_in_processes": ["main", "content"], - "alert_emails": ["seceng-telemetry@mozilla.org"], - "bug_numbers": [1311893], - "expires_in_version": "58", + "record_in_processes": [ "main" ], + "alert_emails": ["seceng-telemetry@mozilla.com"], + "bug_numbers": [1311893, 1359987], + "expires_in_version": "62", "kind": "exponential", "low": 100, "high": 30000,