summaryrefslogtreecommitdiffstats
path: root/toolkit/components/antitracking/URLQueryStringStripper.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /toolkit/components/antitracking/URLQueryStringStripper.cpp
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/antitracking/URLQueryStringStripper.cpp')
-rw-r--r--toolkit/components/antitracking/URLQueryStringStripper.cpp179
1 files changed, 179 insertions, 0 deletions
diff --git a/toolkit/components/antitracking/URLQueryStringStripper.cpp b/toolkit/components/antitracking/URLQueryStringStripper.cpp
new file mode 100644
index 0000000000..581b8fcdfb
--- /dev/null
+++ b/toolkit/components/antitracking/URLQueryStringStripper.cpp
@@ -0,0 +1,179 @@
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "URLQueryStringStripper.h"
+
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/StaticPrefs_privacy.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/Unused.h"
+#include "mozilla/Telemetry.h"
+
+#include "nsEffectiveTLDService.h"
+#include "nsISupportsImpl.h"
+#include "nsIURI.h"
+#include "nsIURIMutator.h"
+#include "nsUnicharUtils.h"
+#include "nsURLHelper.h"
+
+namespace {
+mozilla::StaticRefPtr<mozilla::URLQueryStringStripper> gQueryStringStripper;
+} // namespace
+
+namespace mozilla {
+
+NS_IMPL_ISUPPORTS(URLQueryStringStripper, nsIURLQueryStrippingListObserver)
+
+URLQueryStringStripper* URLQueryStringStripper::GetOrCreate() {
+ if (!gQueryStringStripper) {
+ gQueryStringStripper = new URLQueryStringStripper();
+ gQueryStringStripper->Init();
+
+ RunOnShutdown(
+ [&] {
+ gQueryStringStripper->Shutdown();
+ gQueryStringStripper = nullptr;
+ },
+ ShutdownPhase::XPCOMShutdown);
+ }
+
+ return gQueryStringStripper;
+}
+
+/* static */
+uint32_t URLQueryStringStripper::Strip(nsIURI* aURI, bool aIsPBM,
+ nsCOMPtr<nsIURI>& aOutput) {
+ if (aIsPBM) {
+ if (!StaticPrefs::privacy_query_stripping_enabled_pbmode()) {
+ return 0;
+ }
+ } else {
+ if (!StaticPrefs::privacy_query_stripping_enabled()) {
+ return 0;
+ }
+ }
+
+ RefPtr<URLQueryStringStripper> stripper = GetOrCreate();
+
+ if (stripper->CheckAllowList(aURI)) {
+ return 0;
+ }
+
+ return stripper->StripQueryString(aURI, aOutput);
+}
+
+void URLQueryStringStripper::Init() {
+ mService = do_GetService("@mozilla.org/query-stripping-list-service;1");
+ NS_ENSURE_TRUE_VOID(mService);
+
+ mService->Init();
+ mService->RegisterAndRunObserver(this);
+}
+
+void URLQueryStringStripper::Shutdown() {
+ mList.Clear();
+ mAllowList.Clear();
+
+ mService->UnregisterObserver(this);
+ mService = nullptr;
+}
+
+uint32_t URLQueryStringStripper::StripQueryString(nsIURI* aURI,
+ nsCOMPtr<nsIURI>& aOutput) {
+ MOZ_ASSERT(aURI);
+
+ nsCOMPtr<nsIURI> uri(aURI);
+
+ nsAutoCString query;
+ nsresult rv = aURI->GetQuery(query);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ uint32_t numStripped = 0;
+
+ // We don't need to do anything if there is no query string.
+ if (query.IsEmpty()) {
+ return numStripped;
+ }
+
+ URLParams params;
+
+ URLParams::Parse(query, [&](nsString&& name, nsString&& value) {
+ nsAutoString lowerCaseName;
+
+ ToLowerCase(name, lowerCaseName);
+
+ if (mList.Contains(lowerCaseName)) {
+ numStripped += 1;
+
+ // Count how often a specific query param is stripped. For privacy reasons
+ // this will only count query params listed in the Histogram definition.
+ // Calls for any other query params will be discarded.
+ nsAutoCString telemetryLabel("param_");
+ AppendUTF16toUTF8(lowerCaseName, telemetryLabel);
+ Telemetry::AccumulateCategorical(
+ Telemetry::QUERY_STRIPPING_COUNT_BY_PARAM, telemetryLabel);
+
+ return true;
+ }
+
+ params.Append(name, value);
+ return true;
+ });
+
+ // Return if there is no parameter has been stripped.
+ if (!numStripped) {
+ return numStripped;
+ }
+
+ nsAutoString newQuery;
+ params.Serialize(newQuery, false);
+
+ Unused << NS_MutateURI(uri)
+ .SetQuery(NS_ConvertUTF16toUTF8(newQuery))
+ .Finalize(aOutput);
+
+ return numStripped;
+}
+
+bool URLQueryStringStripper::CheckAllowList(nsIURI* aURI) {
+ MOZ_ASSERT(aURI);
+
+ // Get the site(eTLD+1) from the URI.
+ nsAutoCString baseDomain;
+ nsresult rv =
+ nsEffectiveTLDService::GetInstance()->GetBaseDomain(aURI, 0, baseDomain);
+ if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
+ return false;
+ }
+ NS_ENSURE_SUCCESS(rv, false);
+
+ return mAllowList.Contains(baseDomain);
+}
+
+void URLQueryStringStripper::PopulateStripList(const nsAString& aList) {
+ mList.Clear();
+
+ for (const nsAString& item : aList.Split(' ')) {
+ mList.Insert(item);
+ }
+}
+
+void URLQueryStringStripper::PopulateAllowList(const nsACString& aList) {
+ mAllowList.Clear();
+
+ for (const nsACString& item : aList.Split(',')) {
+ mAllowList.Insert(item);
+ }
+}
+
+NS_IMETHODIMP
+URLQueryStringStripper::OnQueryStrippingListUpdate(
+ const nsAString& aStripList, const nsACString& aAllowList) {
+ PopulateStripList(aStripList);
+ PopulateAllowList(aAllowList);
+ return NS_OK;
+}
+
+} // namespace mozilla