Bug 1720869 - Part 1: Add a telemetry probe for referrer policy. r=ckerschb,necko-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D121344
This commit is contained in:
Tim Huang 2021-08-02 19:24:54 +00:00
parent 002654edda
commit 4cca7fc573
4 changed files with 80 additions and 18 deletions

View File

@ -27,6 +27,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/StaticPrefs_network.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/Telemetry.h"
#include "nsIWebProgressListener.h"
static mozilla::LazyLogModule gReferrerInfoLog("ReferrerInfo");
@ -506,6 +507,36 @@ bool ReferrerInfo::IsCrossOriginRequest(nsIHttpChannel* aChannel) {
return !isSameOrigin;
}
/* static */
bool ReferrerInfo::IsCrossSiteRequest(nsIHttpChannel* aChannel) {
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
if (!loadInfo->TriggeringPrincipal()->GetIsContentPrincipal()) {
LOG(("no triggering URI via loadInfo, assuming load is cross-site"));
return true;
}
if (LOG_ENABLED()) {
nsAutoCString triggeringURISpec;
loadInfo->TriggeringPrincipal()->GetAsciiSpec(triggeringURISpec);
LOG(("triggeringURI=%s\n", triggeringURISpec.get()));
}
nsCOMPtr<nsIURI> uri;
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
bool isCrossSite = true;
rv = loadInfo->TriggeringPrincipal()->IsThirdPartyURI(uri, &isCrossSite);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
return isCrossSite;
}
ReferrerInfo::TrimmingPolicy ReferrerInfo::ComputeTrimmingPolicy(
nsIHttpChannel* aChannel) const {
uint32_t trimmingPolicy = GetUserTrimmingPolicy();
@ -689,24 +720,7 @@ bool ReferrerInfo::ShouldIgnoreLessRestrictedPolicies(
return false;
}
if (!loadInfo->TriggeringPrincipal()->GetIsContentPrincipal()) {
LOG(("no triggering URI via loadInfo, assuming load is cross-site"));
return true;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
bool isCrossSite = true;
rv = loadInfo->TriggeringPrincipal()->IsThirdPartyURI(uri, &isCrossSite);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
return isCrossSite;
return IsCrossSiteRequest(aChannel);
}
void ReferrerInfo::LogMessageToConsole(
@ -1457,5 +1471,22 @@ ReferrerInfo::Write(nsIObjectOutputStream* aStream) {
return NS_OK;
}
void ReferrerInfo::RecordTelemetry(nsIHttpChannel* aChannel) {
#ifdef DEBUG
MOZ_ASSERT(!mTelemetryRecorded);
mTelemetryRecorded = true;
#endif // DEBUG
// The telemetry probe has 18 buckets. The first 9 buckets are for same-site
// requests and the rest 9 buckets are for cross-site requests.
uint32_t telemetryOffset =
IsCrossSiteRequest(aChannel)
? static_cast<uint32_t>(ReferrerPolicy::EndGuard_)
: 0;
Telemetry::Accumulate(Telemetry::REFERRER_POLICY_COUNT,
static_cast<uint32_t>(mPolicy) + telemetryOffset);
}
} // namespace dom
} // namespace mozilla

View File

@ -89,6 +89,9 @@ class ReferrerInfo : public nsIReferrerInfo {
already_AddRefed<ReferrerInfo> CloneWithNewOriginalReferrer(
nsIURI* aOriginalReferrer) const;
// Record the telemetry for the referrer policy.
void RecordTelemetry(nsIHttpChannel* aChannel);
/*
* Helper function to create a new ReferrerInfo object from other. We will not
* pass in any computed values and override referrer policy if needed
@ -180,6 +183,11 @@ class ReferrerInfo : public nsIReferrerInfo {
*/
static bool IsCrossOriginRequest(nsIHttpChannel* aChannel);
/**
* Returns true if the given channel is cross-site request.
*/
static bool IsCrossSiteRequest(nsIHttpChannel* aChannel);
/**
* Returns true if the given channel is suppressed by Referrer-Policy header
* and should set "null" to Origin header.
@ -449,6 +457,12 @@ class ReferrerInfo : public nsIReferrerInfo {
// Store a computed referrer for a given channel
Maybe<nsCString> mComputedReferrer;
#ifdef DEBUG
// Indicates if the telemetry has been recorded. This is used to make sure the
// telemetry will be only recored once.
bool mTelemetryRecorded = false;
#endif // DEBUG
};
} // namespace dom

View File

@ -1627,6 +1627,12 @@ nsresult HttpBaseChannel::SetReferrerInfoInternal(
return NS_ERROR_NOT_INITIALIZED;
}
if (aClone) {
// Record the telemetry once we set the referrer info to the channel
// successfully.
referrerInfo->RecordTelemetry(this);
}
if (aCompute) {
rv = referrerInfo->ComputeReferrer(this);
if (NS_WARN_IF(NS_FAILED(rv))) {

View File

@ -16194,6 +16194,17 @@
"n_buckets": 56,
"description": "How much time (in hours) passed between the current cookie purging activity and the one before that (cookie purging is run on 'daily idle')"
},
"REFERRER_POLICY_COUNT" : {
"products": ["firefox"],
"record_in_processes": ["main"],
"alert_emails": ["tihuang@mozilla.com", "jhofmann@mozilla.com", "ckerschbaumer@mozilla.com", "seceng-telemetry@mozilla.com"],
"expires_in_version": "never",
"kind" : "enumerated",
"n_values": 18,
"bug_numbers": [1720869],
"description": "The counter of each referrer policy which has been computed for a referrer. The buckets (0-8) are for same-site requests and buckets (9-17) are for cross-site requests. Note that the index matches to the order in ReferrerPolicy.webidl",
"releaseChannelCollection": "opt-out"
},
"APZ_ZOOM_ACTIVITY" : {
"products": ["firefox"],
"record_in_processes": ["content"],