Bug 1943650 - Command-line --help output misformatted after --dbus-service. r=emilio
[gecko.git] / toolkit / components / antitracking / bouncetrackingprotection / ClearDataCallback.cpp
blobc974c8ea0122e975051ccef15700127ad4ddb0ef
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "ClearDataCallback.h"
6 #include "mozilla/glean/AntitrackingBouncetrackingprotectionMetrics.h"
7 #include "nsIBounceTrackingProtection.h"
8 #include "nsIURIClassifier.h"
9 #include "mozilla/net/UrlClassifierFeatureFactory.h"
10 #include "nsNetCID.h"
11 #include "nsNetUtil.h"
12 #include "nsServiceManagerUtils.h"
13 #include "mozilla/ClearOnShutdown.h"
15 using namespace mozilla;
17 // Used in automation. Dispatched when a site host has been purged, classified
18 // and telemetry has been collected for the given host.
19 #define TEST_OBSERVER_MSG_RECORDED_PURGE_TELEMETRY \
20 "bounce-tracking-protection-recorded-purge-telemetry"
22 // List of features classifying bounce trackers that have been purged.
23 static constexpr nsLiteralCString kUrlClassifierFeatures[] = {
24 "emailtracking-protection"_ns,
25 "fingerprinting-protection"_ns,
26 "socialtracking-protection"_ns,
27 "tracking-protection"_ns,
29 static_assert(std::size(kUrlClassifierFeatures) > 0,
30 "At least one URL classifier feature must be defined");
32 // List of features for classifying bounce trackers that have been purged.
33 // See kUrlClassifierFeatures for the list of features.
34 static StaticAutoPtr<nsTArray<RefPtr<nsIUrlClassifierFeature>>>
35 sUrlClassifierFeatures;
37 NS_IMPL_ISUPPORTS(ClearDataCallback, nsIClearDataCallback,
38 nsIUrlClassifierFeatureCallback);
40 ClearDataCallback::ClearDataCallback(ClearDataMozPromise::Private* aPromise,
41 const OriginAttributes& aOriginAttributes,
42 const nsACString& aHost,
43 PRTime aBounceTime)
44 : mPromise(aPromise), mClearDurationTimer(0) {
45 MOZ_ASSERT(!aHost.IsEmpty(), "Host must not be empty");
47 mEntry =
48 new BounceTrackingPurgeEntry(aOriginAttributes, aHost, aBounceTime, 0);
50 if (StaticPrefs::privacy_bounceTrackingProtection_mode() ==
51 nsIBounceTrackingProtection::MODE_ENABLED) {
52 // Only collect timing information when actually performing the deletion
53 mClearDurationTimer =
54 glean::bounce_tracking_protection::purge_duration.Start();
55 MOZ_ASSERT(mClearDurationTimer);
58 // Populate feature list for URL classification as needed.
59 if (!sUrlClassifierFeatures) {
60 sUrlClassifierFeatures = new nsTArray<RefPtr<nsIUrlClassifierFeature>>();
62 // Construct the list of classifier features used for purging telemetry.
63 for (const nsCString& featureName : kUrlClassifierFeatures) {
64 nsCOMPtr<nsIUrlClassifierFeature> feature =
65 net::UrlClassifierFeatureFactory::GetFeatureByName(featureName);
66 if (NS_WARN_IF(!feature)) {
67 continue;
69 sUrlClassifierFeatures->AppendElement(feature);
71 MOZ_ASSERT(!sUrlClassifierFeatures->IsEmpty(),
72 "At least one URL classifier feature must be present");
73 RunOnShutdown([] {
74 sUrlClassifierFeatures->Clear();
75 sUrlClassifierFeatures = nullptr;
76 });
80 ClearDataCallback::~ClearDataCallback() {
81 mPromise->Reject(0, __func__);
82 if (mClearDurationTimer) {
83 glean::bounce_tracking_protection::purge_duration.Cancel(
84 std::move(mClearDurationTimer));
88 // nsIClearDataCallback implementation
89 NS_IMETHODIMP ClearDataCallback::OnDataDeleted(uint32_t aFailedFlags) {
90 if (aFailedFlags) {
91 mPromise->Reject(aFailedFlags, __func__);
92 } else {
93 MOZ_LOG(gBounceTrackingProtectionLog, LogLevel::Debug,
94 ("%s: Cleared host: %s, bounceTime: %" PRIu64, __FUNCTION__,
95 PromiseFlatCString(mEntry->SiteHostRef()).get(),
96 mEntry->TimeStampRef()));
98 mEntry->PurgeTimeRef() = PR_Now();
99 mPromise->Resolve(mEntry, __func__);
101 // Only record classifications on successful deletion.
102 RecordURLClassifierTelemetry();
104 // Always collect clear duration and purge count.
105 RecordClearDurationTelemetry();
106 RecordPurgeCountTelemetry(aFailedFlags != 0);
107 RecordPurgeEventTelemetry(aFailedFlags == 0);
109 return NS_OK;
112 void ClearDataCallback::RecordClearDurationTelemetry() {
113 if (mClearDurationTimer) {
114 glean::bounce_tracking_protection::purge_duration.StopAndAccumulate(
115 std::move(mClearDurationTimer));
116 mClearDurationTimer = 0;
120 void ClearDataCallback::RecordPurgeCountTelemetry(bool aFailed) {
121 if (StaticPrefs::privacy_bounceTrackingProtection_mode() ==
122 nsIBounceTrackingProtection::MODE_ENABLED_DRY_RUN) {
123 MOZ_ASSERT(aFailed == 0, "Dry-run purge can't fail");
124 glean::bounce_tracking_protection::purge_count.Get("dry"_ns).Add(1);
125 } else if (aFailed) {
126 glean::bounce_tracking_protection::purge_count.Get("failure"_ns).Add(1);
127 } else {
128 glean::bounce_tracking_protection::purge_count.Get("success"_ns).Add(1);
132 void ClearDataCallback::RecordURLClassifierTelemetry() {
133 nsresult rv = NS_OK;
134 nsCOMPtr<nsIURIClassifier> uriClassifier =
135 do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
136 NS_ENSURE_SUCCESS_VOID(rv);
137 NS_ENSURE_TRUE_VOID(uriClassifier);
139 // Create a copy of the site host because we might have to mutate it.
140 nsAutoCString siteHost(mEntry->SiteHostRef());
141 nsContentUtils::MaybeFixIPv6Host(siteHost);
143 // Create URI from siteHost
144 nsAutoCString uriStr("https://");
145 uriStr.Append(siteHost);
147 nsCOMPtr<nsIURI> uri;
148 rv = NS_NewURI(getter_AddRefs(uri), uriStr);
149 NS_ENSURE_SUCCESS_VOID(rv);
151 MOZ_ASSERT(sUrlClassifierFeatures);
152 rv = uriClassifier->AsyncClassifyLocalWithFeatures(
153 uri, *sUrlClassifierFeatures, nsIUrlClassifierFeature::blocklist, this);
154 NS_ENSURE_SUCCESS_VOID(rv);
157 // nsIUrlClassifierFeatureCallback
158 // Used for telemetry only.
159 NS_IMETHODIMP
160 ClearDataCallback::OnClassifyComplete(
161 const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aResults) {
162 if (!aResults.IsEmpty()) {
163 // Classified as a tracker => Increase Glean counter. We don't have to count
164 // non-classified hosts because we already keep track of the total count of
165 // successful purges.
166 glean::bounce_tracking_protection::purge_count_classified_tracker.Add(1);
169 // In test mode dispatch an observer message to indicate we've completed
170 // collecting telemetry for the purge for the given host. This is needed
171 // because classification happens async.
172 if (StaticPrefs::privacy_bounceTrackingProtection_enableTestMode()) {
173 nsCOMPtr<nsIObserverService> obsSvc =
174 mozilla::services::GetObserverService();
175 NS_ENSURE_TRUE(obsSvc, NS_ERROR_FAILURE);
177 nsresult rv = obsSvc->NotifyObservers(
178 nullptr, TEST_OBSERVER_MSG_RECORDED_PURGE_TELEMETRY,
179 NS_ConvertUTF8toUTF16(mEntry->SiteHostRef()).get());
180 NS_ENSURE_SUCCESS(rv, rv);
183 return NS_OK;
186 void ClearDataCallback::RecordPurgeEventTelemetry(bool aSuccess) {
187 // Record a glean event for the clear action.
188 glean::bounce_tracking_protection::PurgeActionExtra extra = {
189 .bounceTime = Some(mEntry->TimeStampRef() / PR_USEC_PER_SEC),
190 .isDryRun = Some(StaticPrefs::privacy_bounceTrackingProtection_mode() ==
191 nsIBounceTrackingProtection::MODE_ENABLED_DRY_RUN),
192 .siteHost = Some(nsAutoCString(mEntry->SiteHostRef())),
193 .success = Some(aSuccess),
195 glean::bounce_tracking_protection::purge_action.Record(Some(extra));