summaryrefslogtreecommitdiffstats
path: root/toolkit/components/antitracking
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/antitracking')
-rw-r--r--toolkit/components/antitracking/AntiTrackingUtils.cpp135
-rw-r--r--toolkit/components/antitracking/StorageAccess.h2
-rw-r--r--toolkit/components/antitracking/StorageAccessAPIHelper.cpp8
-rw-r--r--toolkit/components/antitracking/StoragePrincipalHelper.cpp41
-rw-r--r--toolkit/components/antitracking/StoragePrincipalHelper.h8
-rw-r--r--toolkit/components/antitracking/StripOnShareLists/LGPL/LICENSE165
-rw-r--r--toolkit/components/antitracking/StripOnShareLists/LGPL/StripOnShareLGPL.json556
-rw-r--r--toolkit/components/antitracking/StripOnShareLists/MPL2/StripOnShare.json (renamed from toolkit/components/antitracking/data/StripOnShare.json)2
-rw-r--r--toolkit/components/antitracking/URLDecorationStripper.cpp8
-rw-r--r--toolkit/components/antitracking/URLQueryStringStripper.cpp189
-rw-r--r--toolkit/components/antitracking/URLQueryStringStripper.h10
-rw-r--r--toolkit/components/antitracking/URLQueryStrippingListService.sys.mjs56
-rw-r--r--toolkit/components/antitracking/jar.mn5
-rw-r--r--toolkit/components/antitracking/nsIURLQueryStringStripper.idl2
-rw-r--r--toolkit/components/antitracking/nsIURLQueryStrippingListService.idl2
-rw-r--r--toolkit/components/antitracking/test/browser/browser.toml12
-rw-r--r--toolkit/components/antitracking/test/browser/browser_doublyNestedTracker.js2
-rw-r--r--toolkit/components/antitracking/test/browser/browser_partitionedABA.js86
-rw-r--r--toolkit/components/antitracking/test/browser/browser_staticPartition_cache.js4
-rw-r--r--toolkit/components/antitracking/test/browser/browser_staticPartition_saveAs.js4
-rw-r--r--toolkit/components/antitracking/test/browser/browser_storageAccessThirdPartyChecks_alwaysPartition.js1
-rw-r--r--toolkit/components/antitracking/test/browser/file_saveAsPageInfo.html2
-rw-r--r--toolkit/components/antitracking/test/browser/file_video.ogvbin16049 -> 0 bytes
-rw-r--r--toolkit/components/antitracking/test/browser/file_video.webmbin0 -> 17931 bytes
-rw-r--r--toolkit/components/antitracking/test/gtest/TestStoragePrincipalHelper.cpp2
-rw-r--r--toolkit/components/antitracking/test/xpcshell/test_validate_strip_on_share_list.js141
26 files changed, 1233 insertions, 210 deletions
diff --git a/toolkit/components/antitracking/AntiTrackingUtils.cpp b/toolkit/components/antitracking/AntiTrackingUtils.cpp
index 2c530dc3da..d9624237de 100644
--- a/toolkit/components/antitracking/AntiTrackingUtils.cpp
+++ b/toolkit/components/antitracking/AntiTrackingUtils.cpp
@@ -514,6 +514,10 @@ AntiTrackingUtils::GetStoragePermissionStateInParent(nsIChannel* aChannel) {
return nsILoadInfo::NoStoragePermission;
}
+ if (targetPrincipal->IsSystemPrincipal()) {
+ return nsILoadInfo::HasStoragePermission;
+ }
+
nsCOMPtr<nsIURI> trackingURI;
rv = aChannel->GetURI(getter_AddRefs(trackingURI));
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -821,7 +825,8 @@ void AntiTrackingUtils::ComputeIsThirdPartyToTopWindow(nsIChannel* aChannel) {
// whether the page is third-party, so we use channel result principal
// instead. By doing this, an the resource inherits the principal from
// its parent is considered not a third-party.
- if (NS_IsAboutBlank(uri) || NS_IsAboutSrcdoc(uri)) {
+ if (NS_IsAboutBlank(uri) || NS_IsAboutSrcdoc(uri) ||
+ uri->SchemeIs("blob")) {
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
if (NS_WARN_IF(!ssm)) {
return;
@@ -847,10 +852,36 @@ void AntiTrackingUtils::ComputeIsThirdPartyToTopWindow(nsIChannel* aChannel) {
bool AntiTrackingUtils::IsThirdPartyChannel(nsIChannel* aChannel) {
MOZ_ASSERT(aChannel);
- // We only care whether the channel is 3rd-party with respect to
- // the top-level.
- nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
- return loadInfo->GetIsThirdPartyContextToTopWindow();
+ // We have to handle blob URLs here because they always fail
+ // IsThirdPartyChannel because of how blob URLs are constructed. We just
+ // recompare to their ancestor chain from the loadInfo, bailing if any is
+ // third party.
+ nsAutoCString scheme;
+ nsCOMPtr<nsIURI> channelURI;
+ nsresult rv = aChannel->GetURI(getter_AddRefs(channelURI));
+ if (NS_SUCCEEDED(rv) && channelURI->SchemeIs("blob")) {
+ nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
+ for (const nsCOMPtr<nsIPrincipal>& principal :
+ loadInfo->AncestorPrincipals()) {
+ bool thirdParty = true;
+ rv = loadInfo->PrincipalToInherit()->IsThirdPartyPrincipal(principal,
+ &thirdParty);
+ if (NS_SUCCEEDED(rv) && thirdParty) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ nsCOMPtr<mozIThirdPartyUtil> tpuService =
+ mozilla::components::ThirdPartyUtil::Service();
+ if (!tpuService) {
+ return true;
+ }
+ bool thirdParty = true;
+ rv = tpuService->IsThirdPartyChannel(aChannel, nullptr, &thirdParty);
+ NS_ENSURE_SUCCESS(rv, true);
+ return thirdParty;
}
/* static */
@@ -903,19 +934,29 @@ bool AntiTrackingUtils::IsThirdPartyWindow(nsPIDOMWindowInner* aWindow,
/* static */
bool AntiTrackingUtils::IsThirdPartyDocument(Document* aDocument) {
MOZ_ASSERT(aDocument);
- if (!aDocument->GetChannel()) {
+ nsCOMPtr<mozIThirdPartyUtil> tpuService =
+ mozilla::components::ThirdPartyUtil::Service();
+ if (!tpuService) {
+ return true;
+ }
+ bool thirdParty = true;
+ if (!aDocument->GetChannel() ||
+ aDocument->GetDocumentURI()->SchemeIs("blob")) {
// If we can't get the channel from the document, i.e. initial about:blank
// page, we use the browsingContext of the document to check if it's in the
// third-party context. If the browsing context is still not available, we
// will treat the window as third-party.
+ // We also rely on IsThirdPartyContext for blob documents because the
+ // IsThirdPartyChannel check relies on getting the BaseDomain,
+ // which correctly fails for blobs URIs.
RefPtr<BrowsingContext> bc = aDocument->GetBrowsingContext();
return bc ? IsThirdPartyContext(bc) : true;
}
- // We only care whether the channel is 3rd-party with respect to
- // the top-level.
- nsCOMPtr<nsILoadInfo> loadInfo = aDocument->GetChannel()->LoadInfo();
- return loadInfo->GetIsThirdPartyContextToTopWindow();
+ nsresult rv = tpuService->IsThirdPartyChannel(aDocument->GetChannel(),
+ nullptr, &thirdParty);
+ NS_ENSURE_SUCCESS(rv, true);
+ return thirdParty;
}
/* static */
@@ -923,41 +964,47 @@ bool AntiTrackingUtils::IsThirdPartyContext(BrowsingContext* aBrowsingContext) {
MOZ_ASSERT(aBrowsingContext);
MOZ_ASSERT(aBrowsingContext->IsInProcess());
- if (aBrowsingContext->IsTopContent()) {
- return false;
- }
-
- // If the top browsing context is not in the same process, it's cross-origin.
- if (!aBrowsingContext->Top()->IsInProcess()) {
- return true;
- }
-
+ // iframes with SANDBOX_ORIGIN are always third-party contexts
+ // because they are a unique origin
nsIDocShell* docShell = aBrowsingContext->GetDocShell();
if (!docShell) {
return true;
}
Document* doc = docShell->GetExtantDocument();
- if (!doc) {
+ if (!doc || doc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
return true;
}
nsIPrincipal* principal = doc->NodePrincipal();
- nsIDocShell* topDocShell = aBrowsingContext->Top()->GetDocShell();
- if (!topDocShell) {
- return true;
- }
- Document* topDoc = topDocShell->GetDocument();
- if (!topDoc) {
- return true;
- }
- nsIPrincipal* topPrincipal = topDoc->NodePrincipal();
+ BrowsingContext* traversingParent = aBrowsingContext->GetParent();
+ while (traversingParent) {
+ // If the parent browsing context is not in the same process, it's
+ // cross-origin.
+ if (!traversingParent->IsInProcess()) {
+ return true;
+ }
- auto* topBasePrin = BasePrincipal::Cast(topPrincipal);
- bool isThirdParty = true;
+ nsIDocShell* parentDocShell = traversingParent->GetDocShell();
+ if (!parentDocShell) {
+ return true;
+ }
+ Document* parentDoc = parentDocShell->GetDocument();
+ if (!parentDoc || parentDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
+ return true;
+ }
+ nsIPrincipal* parentPrincipal = parentDoc->NodePrincipal();
+
+ auto* parentBasePrin = BasePrincipal::Cast(parentPrincipal);
+ bool isThirdParty = true;
- topBasePrin->IsThirdPartyPrincipal(principal, &isThirdParty);
+ parentBasePrin->IsThirdPartyPrincipal(principal, &isThirdParty);
+ if (isThirdParty) {
+ return true;
+ }
- return isThirdParty;
+ traversingParent = traversingParent->GetParent();
+ }
+ return false;
}
/* static */
@@ -1005,6 +1052,18 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
->MarkOverriddenFingerprintingSettingsAsSet();
#endif
+ ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
+ if (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
+ contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
+ nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
+ Unused << loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
+ // For subdocuments, the channel's partition key is that of the parent
+ // document. This document may have a different partition key, particularly
+ // one without the same-site bit.
+ net::CookieJarSettings::Cast(cookieJarSettings)
+ ->UpdatePartitionKeyForDocumentLoadedByChannel(aChannel);
+ }
+
// We only update the IsOnContentBlockingAllowList flag and the partition key
// for the top-level http channel.
//
@@ -1015,17 +1074,15 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
// The partition key is computed based on the site, so it's no point to set it
// for channels other than http channels.
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
- if (!httpChannel || loadInfo->GetExternalContentPolicyType() !=
- ExtContentPolicy::TYPE_DOCUMENT) {
+ if (!httpChannel || contentType != ExtContentPolicy::TYPE_DOCUMENT) {
return;
}
- nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
- Unused << loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
-
// Update the IsOnContentBlockingAllowList flag in the CookieJarSettings
// if this is a top level loading. For sub-document loading, this flag
// would inherit from the parent.
+ nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
+ Unused << loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
net::CookieJarSettings::Cast(cookieJarSettings)
->UpdateIsOnContentBlockingAllowList(aChannel);
@@ -1033,7 +1090,7 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
// propagated to non-top level loads via CookieJarSetting.
nsCOMPtr<nsIURI> uri;
Unused << aChannel->GetURI(getter_AddRefs(uri));
- net::CookieJarSettings::Cast(cookieJarSettings)->SetPartitionKey(uri);
+ net::CookieJarSettings::Cast(cookieJarSettings)->SetPartitionKey(uri, false);
// Generate the fingerprinting randomization key for top-level loads. The key
// will automatically be propagated to sub loads.
diff --git a/toolkit/components/antitracking/StorageAccess.h b/toolkit/components/antitracking/StorageAccess.h
index 4dbd5355c0..bca26057f3 100644
--- a/toolkit/components/antitracking/StorageAccess.h
+++ b/toolkit/components/antitracking/StorageAccess.h
@@ -40,8 +40,6 @@ enum class StorageAccess {
// Allow access to the storage, but only if it is secure to do so in a
// private browsing context.
ePrivateBrowsing = 1,
- // Allow access to the storage, but only persist it for the current session
- eSessionScoped = 2,
// Allow access to the storage
eAllow = 3,
// Keep this at the end. Used for serialization, but not a valid value.
diff --git a/toolkit/components/antitracking/StorageAccessAPIHelper.cpp b/toolkit/components/antitracking/StorageAccessAPIHelper.cpp
index 5baa2c2557..b4fcf2f6e9 100644
--- a/toolkit/components/antitracking/StorageAccessAPIHelper.cpp
+++ b/toolkit/components/antitracking/StorageAccessAPIHelper.cpp
@@ -475,7 +475,6 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
[aParentContext, aTopLevelWindowId, trackingOrigin, trackingPrincipal,
aCookieBehavior,
aReason](int aAllowMode) -> RefPtr<StorageAccessPermissionGrantPromise> {
- MOZ_ASSERT(!aParentContext->IsInProcess());
// We don't have the window, send an IPC to the content process that
// owns the parent window. But there is a special case, for window.open,
// we'll return to the content process we need to inform when this
@@ -1060,12 +1059,7 @@ StorageAccessAPIHelper::CheckSameSiteCallingContextDecidesStorageAccessAPI(
}
}
- nsIChannel* chan = aDocument->GetChannel();
- if (!chan) {
- return Some(false);
- }
- nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
- if (loadInfo->GetIsThirdPartyContextToTopWindow()) {
+ if (AntiTrackingUtils::IsThirdPartyDocument(aDocument)) {
return Some(false);
}
diff --git a/toolkit/components/antitracking/StoragePrincipalHelper.cpp b/toolkit/components/antitracking/StoragePrincipalHelper.cpp
index 10be1112ca..79bafead2c 100644
--- a/toolkit/components/antitracking/StoragePrincipalHelper.cpp
+++ b/toolkit/components/antitracking/StoragePrincipalHelper.cpp
@@ -86,8 +86,10 @@ bool ChooseOriginAttributes(nsIChannel* aChannel, OriginAttributes& aAttrs,
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
-
- aAttrs.SetPartitionKey(principalURI);
+ bool foreignByAncestorContext =
+ AntiTrackingUtils::IsThirdPartyChannel(aChannel) &&
+ !loadInfo->GetIsThirdPartyContextToTopWindow();
+ aAttrs.SetPartitionKey(principalURI, foreignByAncestorContext);
return true;
}
@@ -313,7 +315,7 @@ nsresult StoragePrincipalHelper::GetPrincipal(nsIChannel* aChannel,
// We only support foreign partitioned principal when dFPI is enabled.
if (cjs->GetCookieBehavior() ==
nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
- loadInfo->GetIsThirdPartyContextToTopWindow()) {
+ AntiTrackingUtils::IsThirdPartyChannel(aChannel)) {
outPrincipal = partitionedPrincipal;
}
break;
@@ -435,7 +437,7 @@ bool StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
return false;
}
- return aWorkerPrivate->IsThirdPartyContextToTopWindow();
+ return aWorkerPrivate->IsThirdPartyContext();
}
// static
@@ -479,7 +481,7 @@ bool StoragePrincipalHelper::GetOriginAttributes(
// Otherwise, we will use the regular principal.
if (cjs->GetCookieBehavior() ==
nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
- loadInfo->GetIsThirdPartyContextToTopWindow()) {
+ AntiTrackingUtils::IsThirdPartyChannel(aChannel)) {
ChooseOriginAttributes(aChannel, aAttributes, true);
}
break;
@@ -560,7 +562,7 @@ void StoragePrincipalHelper::UpdateOriginAttributesForNetworkState(
return;
}
- aAttributes.SetPartitionKey(aFirstPartyURI);
+ aAttributes.SetPartitionKey(aFirstPartyURI, false);
}
enum SupportedScheme { HTTP, HTTPS };
@@ -664,8 +666,9 @@ bool StoragePrincipalHelper::PartitionKeyHasBaseDomain(
nsString scheme;
nsString pkBaseDomain;
int32_t port;
- bool success = OriginAttributes::ParsePartitionKey(aPartitionKey, scheme,
- pkBaseDomain, port);
+ bool foreign;
+ bool success = OriginAttributes::ParsePartitionKey(
+ aPartitionKey, scheme, pkBaseDomain, port, foreign);
if (!success) {
return false;
@@ -674,4 +677,26 @@ bool StoragePrincipalHelper::PartitionKeyHasBaseDomain(
return aBaseDomain.Equals(pkBaseDomain);
}
+// static
+void StoragePrincipalHelper::UpdatePartitionKeyWithForeignAncestorBit(
+ nsAString& aKey, bool aForeignByAncestorContext) {
+ bool site = 0 == aKey.Find(u"(");
+ if (!site) {
+ return;
+ }
+ if (aForeignByAncestorContext) {
+ int32_t index = aKey.Find(u",f)");
+ if (index == -1) {
+ uint32_t cutStart = aKey.Length() - 1;
+ aKey.ReplaceLiteral(cutStart, 1, u",f)");
+ }
+ } else {
+ int32_t index = aKey.Find(u",f)");
+ if (index != -1) {
+ uint32_t cutLength = aKey.Length() - index;
+ aKey.ReplaceLiteral(index, cutLength, u")");
+ }
+ }
+}
+
} // namespace mozilla
diff --git a/toolkit/components/antitracking/StoragePrincipalHelper.h b/toolkit/components/antitracking/StoragePrincipalHelper.h
index f813417eb6..0fe362d8c1 100644
--- a/toolkit/components/antitracking/StoragePrincipalHelper.h
+++ b/toolkit/components/antitracking/StoragePrincipalHelper.h
@@ -351,6 +351,14 @@ class StoragePrincipalHelper final {
static bool PartitionKeyHasBaseDomain(const nsAString& aPartitionKey,
const nsAString& aBaseDomain);
+
+ // Partition keys can have the same-site bit added or removed from them.
+ // "(https,foo.com)", false -> "(https,foo.com)"
+ // "(https,foo.com,f)", false -> "(https,foo.com)"
+ // "(https,foo.com,f)", true -> "(https,foo.com,f)"
+ // "(https,foo.com)", true -> "(https,foo.com,f)"
+ static void UpdatePartitionKeyWithForeignAncestorBit(
+ nsAString& aKey, bool aForeignByAncestorContext);
};
} // namespace mozilla
diff --git a/toolkit/components/antitracking/StripOnShareLists/LGPL/LICENSE b/toolkit/components/antitracking/StripOnShareLists/LGPL/LICENSE
new file mode 100644
index 0000000000..6600f1c98d
--- /dev/null
+++ b/toolkit/components/antitracking/StripOnShareLists/LGPL/LICENSE
@@ -0,0 +1,165 @@
+GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/toolkit/components/antitracking/StripOnShareLists/LGPL/StripOnShareLGPL.json b/toolkit/components/antitracking/StripOnShareLists/LGPL/StripOnShareLGPL.json
new file mode 100644
index 0000000000..b34fbfff6b
--- /dev/null
+++ b/toolkit/components/antitracking/StripOnShareLists/LGPL/StripOnShareLGPL.json
@@ -0,0 +1,556 @@
+{
+ "global": {
+ "queryParams": [
+ "at_campaign",
+ "at_send_date",
+ "at_campaign_type",
+ "at_recipient_list",
+ "at_creation",
+ "at_recipient_id",
+ "at_emailtype",
+ "at_ptr_name",
+ "at_link",
+ "at_link_id",
+ "at_medium",
+ "at_link_type",
+ "at_link_origin",
+ "utm_email",
+ "utm_email_id",
+ "utm_campaign_id",
+ "utm_newsletter_id"
+ ],
+ "topLevelSites": ["*"]
+ },
+ "twitter": {
+ "queryParams": ["refsrc", "cxt", "s"],
+ "topLevelSites": ["www.twitter.com", "twitter.com", "x.com"]
+ },
+ "amazon": {
+ "queryParams": [
+ "pd_rd_i",
+ "pf_rd_i",
+ "pf_rd_m",
+ "pf_rd_s",
+ "pf_rd_t",
+ "pf_rd_w",
+ "adgrpid",
+ "ascsubtag",
+ "creative",
+ "creativeASIN",
+ "dchild",
+ "field-lbr_brands_browse-bin",
+ "hvadid",
+ "hvbmt",
+ "hvdev",
+ "hvlocphy",
+ "hvnetw",
+ "hvrand",
+ "hvtargid",
+ "hydadcr",
+ "initialIssue",
+ "ingress",
+ "linkCode",
+ "linkId",
+ "plattr",
+ "qid",
+ "rdc",
+ "refRID",
+ "th",
+ "ts_id",
+ "visitId",
+ "vtr",
+ "spIA",
+ "_encoding",
+ "qualifier"
+ ],
+ "topLevelSites": [
+ "www.amazon.com",
+ "www.amazon.de",
+ "www.amazon.nl",
+ "www.amazon.fr",
+ "www.amazon.co.jp",
+ "www.amazon.in",
+ "www.amazon.es",
+ "www.amazon.ac",
+ "www.amazon.cn",
+ "www.amazon.eg",
+ "www.amazon.in",
+ "www.amazon.co.uk",
+ "www.amazon.it",
+ "www.amazon.pl",
+ "www.amazon.sg",
+ "www.amazon.ca"
+ ]
+ },
+ "youtube": {
+ "queryParams": ["si", "feature", "kw"],
+ "topLevelSites": ["www.youtube.com", "www.youtu.be"]
+ },
+ "carousell": {
+ "queryParams": [
+ "referrer_search_query",
+ "referrer_search_query_source",
+ "referrer_request_id",
+ "referrer_sort_by",
+ "referrer_source",
+ "referrer_page_type",
+ "referrer_category_id",
+ "t-source",
+ "tap_index",
+ "t-referrer_browse_type",
+ "t-id"
+ ],
+ "topLevelSites": [
+ "ca.carousell.com",
+ "www.carousell.sg",
+ "www.carousell.com.hk",
+ "us.carousell.com",
+ "au.carousell.com"
+ ]
+ },
+ "etsy": {
+ "queryParams": ["click_sum", "ref", "click_key", "organic_search_click"],
+ "topLevelSites": ["www.etsy.com"]
+ },
+ "wikipedia": {
+ "queryParams": ["wprov"],
+ "topLevelSites": ["www.wikipedia.org"]
+ },
+ "wallstreetjournal": {
+ "queryParams": ["reflink"],
+ "topLevelSites": ["www.wsj.com"]
+ },
+ "theathletic": {
+ "queryParams": ["source"],
+ "topLevelSites": ["theathletic.com"]
+ },
+ "forbes": {
+ "queryParams": ["sh"],
+ "topLevelSites": ["www.forbes.com"]
+ },
+ "bloomberg": {
+ "queryParams": ["leadSource", "sref", "srnd"],
+ "topLevelSites": ["www.bloomberg.com"]
+ },
+ "tiktok": {
+ "queryParams": [
+ "share_app_id",
+ "share_author_id",
+ "tt_from",
+ "embed_source",
+ "referer_url",
+ "refer",
+ "is_from_webapp",
+ "sender_device",
+ "sec_uid",
+ "web_id",
+ "enter_method",
+ "t",
+ "q"
+ ],
+ "topLevelSites": ["www.tiktok.com"]
+ },
+ "bbc": {
+ "queryParams": [
+ "facebook_page",
+ "at_bbc_team",
+ "ocid",
+ "ns_mchannel",
+ "ns_source",
+ "ns_campaign",
+ "ns_linkname",
+ "ns_fee",
+ "xtor"
+ ],
+ "topLevelSites": ["www.bbc.com"]
+ },
+ "cnn": {
+ "queryParams": ["ref"],
+ "topLevelSites": ["www.cnn.co.jp", "www.cnn.com"]
+ },
+ "imdb": {
+ "queryParams": [
+ "pf_rd_p",
+ "pf_rd_i",
+ "pf_rd_m",
+ "pf_rd_s",
+ "pf_rd_t",
+ "pf_rd_r"
+ ],
+ "topLevelSites": ["www.imdb.com"]
+ },
+ "mirror": {
+ "queryParams": ["int_source"],
+ "topLevelSites": ["www.mirror.co.uk"]
+ },
+ "wise": {
+ "queryParams": ["partnerizecampaignID", "clickref", "adref", "partnerID"],
+ "topLevelSites": ["wise.com"]
+ },
+ "facebook": {
+ "queryParams": ["tracking", "extid", "mibextid"],
+ "topLevelSites": ["www.facebook.com"]
+ },
+ "lazada": {
+ "queryParams": [
+ "mkttid",
+ "laz_trackid",
+ "spm",
+ "clickTrackInfo",
+ "trafficFrom",
+ "scm",
+ "acm",
+ "ad_src",
+ "did",
+ "mp",
+ "cid",
+ "pos"
+ ],
+ "topLevelSites": [
+ "www.lazada.com.ph",
+ "www.lazada.vn",
+ "www.lazada.sg",
+ "www.lazada.com.my"
+ ]
+ },
+ "msn": {
+ "queryParams": ["cvid", "pc", "ei"],
+ "topLevelSites": ["www.msn.com"]
+ },
+ "aliexpress": {
+ "queryParams": [
+ "sk",
+ "dp",
+ "spm",
+ "scm",
+ "pvid",
+ "scm_id",
+ "scm-url",
+ "utparam",
+ "aff_fsk",
+ "aff_fcid",
+ "terminal_id",
+ "aff_trace_key",
+ "pdp_npi",
+ "aff_short_key",
+ "aff_platform",
+ "algo_pvid",
+ "curPageLogUid",
+ "mall_affr",
+ "algo_expid",
+ "gps-id"
+ ],
+ "topLevelSites": ["www.tiktok.com"]
+ },
+ "reddit": {
+ "queryParams": [
+ "ref",
+ "ref_source",
+ "ref_campaign",
+ "correlation_id",
+ "share_id"
+ ],
+ "topLevelSites": ["www.reddit.com"]
+ },
+ "wired": {
+ "queryParams": ["mbid"],
+ "topLevelSites": ["www.wired.co.uk", "www.wired.com"]
+ },
+ "yandex": {
+ "queryParams": [
+ "utm-term",
+ "did",
+ "from",
+ "msid",
+ "stid",
+ "mlid",
+ "persistent_id",
+ "source-serpid",
+ "suggest_reqid",
+ "clid"
+ ],
+ "topLevelSites": ["yandex.com"]
+ },
+ "ebay": {
+ "queryParams": [
+ "_trkparms",
+ "mkcid",
+ "_trksid",
+ "mkevt",
+ "amdata",
+ "ssuid",
+ "mkrid",
+ "campid",
+ "sssrc",
+ "ssspo",
+ "_from",
+ "hash"
+ ],
+ "topLevelSites": ["www.ebay.com"]
+ },
+ "flipkart": {
+ "queryParams": [
+ "_refId",
+ "store",
+ "ssid",
+ "affid",
+ "cid",
+ "iid",
+ "pwsvid",
+ "pageUID",
+ "lid"
+ ],
+ "topLevelSites": ["www.flipkart.com"]
+ },
+ "google": {
+ "queryParams": [
+ "sca_esv",
+ "ved",
+ "pcampaignid",
+ "rlz",
+ "ei",
+ "sxsrf",
+ "sourceid",
+ "aqs",
+ "cad",
+ "usg",
+ "dpr",
+ "dcr",
+ "sei",
+ "cd",
+ "vet",
+ "esrc",
+ "site",
+ "gs_l",
+ "gs_lp",
+ "sclient",
+ "oe",
+ "visit_id",
+ "biw",
+ "bih",
+ "gs_lcp",
+ "gs_lcrp"
+ ],
+ "topLevelSites": [
+ "www.google.com",
+ "www.google.ad",
+ "www.google.ae",
+ "www.google.com.af",
+ "www.google.com.ag",
+ "www.google.al",
+ "www.google.am",
+ "www.google.co.ao",
+ "www.google.com.ar",
+ "www.google.as",
+ "www.google.at",
+ "www.google.com.au",
+ "www.google.az",
+ "www.google.ba",
+ "www.google.com.bd",
+ "www.google.be",
+ "www.google.bf",
+ "www.google.bg",
+ "www.google.com.bh",
+ "www.google.bi",
+ "www.google.bj",
+ "www.google.com.bn",
+ "www.google.com.bo",
+ "www.google.com.br",
+ "www.google.bs",
+ "www.google.bt",
+ "www.google.co.bw",
+ "www.google.by",
+ "www.google.com.bz",
+ "www.google.ca",
+ "www.google.cd",
+ "www.google.cf",
+ "www.google.cg",
+ "www.google.ch",
+ "www.google.ci",
+ "www.google.co.ck",
+ "www.google.cl",
+ "www.google.cm",
+ "www.google.cn",
+ "www.google.com.co",
+ "www.google.co.cr",
+ "www.google.com.cu",
+ "www.google.cv",
+ "www.google.com.cy",
+ "www.google.cz",
+ "www.google.de",
+ "www.google.dj",
+ "www.google.dk",
+ "www.google.dm",
+ "www.google.com.do",
+ "www.google.dz",
+ "www.google.com.ec",
+ "www.google.ee",
+ "www.google.com.eg",
+ "www.google.es",
+ "www.google.com.et",
+ "www.google.fi",
+ "www.google.com.fj",
+ "www.google.fm",
+ "www.google.fr",
+ "www.google.ga",
+ "www.google.ge",
+ "www.google.gg",
+ "www.google.com.gh",
+ "www.google.com.gi",
+ "www.google.gl",
+ "www.google.gm",
+ "www.google.gr",
+ "www.google.com.gt",
+ "www.google.gy",
+ "www.google.com.hk",
+ "www.google.hn",
+ "www.google.hr",
+ "www.google.ht",
+ "www.google.hu",
+ "www.google.co.id",
+ "www.google.ie",
+ "www.google.co.il",
+ "www.google.im",
+ "www.google.co.in",
+ "www.google.iq",
+ "www.google.is",
+ "www.google.it",
+ "www.google.je",
+ "www.google.com.jm",
+ "www.google.jo",
+ "www.google.co.jp",
+ "www.google.co.ke",
+ "www.google.com.kh",
+ "www.google.ki",
+ "www.google.kg",
+ "www.google.co.kr",
+ "www.google.com.kw",
+ "www.google.kz",
+ "www.google.la",
+ "www.google.com.lb",
+ "www.google.li",
+ "www.google.lk",
+ "www.google.co.ls",
+ "www.google.lt",
+ "www.google.lu",
+ "www.google.lv",
+ "www.google.com.ly",
+ "www.google.co.ma",
+ "www.google.md",
+ "www.google.me",
+ "www.google.mg",
+ "www.google.mk",
+ "www.google.ml",
+ "www.google.com.mm",
+ "www.google.mn",
+ "www.google.com.mt",
+ "www.google.mu",
+ "www.google.mv",
+ "www.google.mw",
+ "www.google.com.mx",
+ "www.google.com.my",
+ "www.google.co.mz",
+ "www.google.com.na",
+ "www.google.com.ng",
+ "www.google.com.ni",
+ "www.google.ne",
+ "www.google.nl",
+ "www.google.no",
+ "www.google.com.np",
+ "www.google.nr",
+ "www.google.nu",
+ "www.google.co.nz",
+ "www.google.com.om",
+ "www.google.com.pa",
+ "www.google.com.pe",
+ "www.google.com.pg",
+ "www.google.com.ph",
+ "www.google.com.pk",
+ "www.google.pl",
+ "www.google.pn",
+ "www.google.com.pr",
+ "www.google.ps",
+ "www.google.pt",
+ "www.google.com.py",
+ "www.google.com.qa",
+ "www.google.ro",
+ "www.google.ru",
+ "www.google.rw",
+ "www.google.com.sa",
+ "www.google.com.sb",
+ "www.google.sc",
+ "www.google.se",
+ "www.google.com.sg",
+ "www.google.sh",
+ "www.google.si",
+ "www.google.sk",
+ "www.google.com.sl",
+ "www.google.sn",
+ "www.google.so",
+ "www.google.sm",
+ "www.google.sr",
+ "www.google.st",
+ "www.google.com.sv",
+ "www.google.td",
+ "www.google.tg",
+ "www.google.co.th",
+ "www.google.com.tj",
+ "www.google.tl",
+ "www.google.tm",
+ "www.google.tn",
+ "www.google.to",
+ "www.google.com.tr",
+ "www.google.tt",
+ "www.google.com.tw",
+ "www.google.co.tz",
+ "www.google.com.ua",
+ "www.google.co.ug",
+ "www.google.co.uk",
+ "www.google.com.uy",
+ "www.google.co.uz",
+ "www.google.com.vc",
+ "www.google.co.ve",
+ "www.google.co.vi",
+ "www.google.com.vn",
+ "www.google.vu",
+ "www.google.ws",
+ "www.google.rs",
+ "www.google.co.za",
+ "www.google.co.zm",
+ "www.google.co.zw",
+ "www.google.cat"
+ ]
+ },
+ "bing": {
+ "queryParams": ["qp", "cvid", "qs", "form", "sk", "sc", "sp"],
+ "topLevelSites": ["www.bing.com"]
+ },
+ "twitch": {
+ "queryParams": ["tt_content", "tt_medium"],
+ "topLevelSites": ["www.twitch.tv"]
+ },
+ "cnet": {
+ "queryParams": ["ftag"],
+ "topLevelSites": ["www.cnet.com"]
+ },
+ "nytimes": {
+ "queryParams": ["smid"],
+ "topLevelSites": ["www.nytimes.com"]
+ },
+ "github": {
+ "queryParams": ["email_token", "email_source"],
+ "topLevelSites": ["github.com"]
+ },
+ "linkedin": {
+ "queryParams": ["refId", "trk", "trackingId"],
+ "topLevelSites": ["ca.linkedin.com"]
+ },
+ "newyorker": {
+ "queryParams": ["esrc", "bxid", "cndid", "source", "mbid"],
+ "topLevelSites": ["www.newyorker.com"]
+ },
+ "bestbuy": {
+ "queryParams": ["acampID", "irclickid", "irgwc", "loc", "mpid", "intl"],
+ "topLevelSites": ["www.bestbuy.com"]
+ }
+}
diff --git a/toolkit/components/antitracking/data/StripOnShare.json b/toolkit/components/antitracking/StripOnShareLists/MPL2/StripOnShare.json
index 394723fa00..00cc973af6 100644
--- a/toolkit/components/antitracking/data/StripOnShare.json
+++ b/toolkit/components/antitracking/StripOnShareLists/MPL2/StripOnShare.json
@@ -55,7 +55,7 @@
},
"twitter": {
"queryParams": ["ref_src", "ref_url"],
- "topLevelSites": ["www.twitter.com", "twitter.com"]
+ "topLevelSites": ["www.twitter.com", "twitter.com", "x.com"]
},
"instagram": {
"queryParams": ["igshid", "ig_rid"],
diff --git a/toolkit/components/antitracking/URLDecorationStripper.cpp b/toolkit/components/antitracking/URLDecorationStripper.cpp
index 38af391945..fc94fe8ed5 100644
--- a/toolkit/components/antitracking/URLDecorationStripper.cpp
+++ b/toolkit/components/antitracking/URLDecorationStripper.cpp
@@ -22,8 +22,8 @@ namespace mozilla {
nsresult URLDecorationStripper::StripTrackingIdentifiers(nsIURI* aURI,
nsACString& aOutSpec) {
- nsAutoString tokenList;
- nsresult rv = Preferences::GetString(kPrefName, tokenList);
+ nsAutoCString tokenList;
+ nsresult rv = Preferences::GetCString(kPrefName, tokenList);
ToLowerCase(tokenList);
nsAutoCString path;
@@ -34,12 +34,12 @@ nsresult URLDecorationStripper::StripTrackingIdentifiers(nsIURI* aURI,
int32_t queryBegins = path.FindChar('?');
// Only positive values are valid since the path must begin with a '/'.
if (queryBegins > 0) {
- for (const nsAString& token : tokenList.Split(' ')) {
+ for (const nsACString& token : tokenList.Split(' ')) {
if (token.IsEmpty()) {
continue;
}
- nsAutoString value;
+ nsAutoCString value;
if (URLParams::Extract(Substring(path, queryBegins + 1), token, value) &&
!value.IsVoid()) {
// Tracking identifier found in the URL!
diff --git a/toolkit/components/antitracking/URLQueryStringStripper.cpp b/toolkit/components/antitracking/URLQueryStringStripper.cpp
index 2e154b9103..5eb513472b 100644
--- a/toolkit/components/antitracking/URLQueryStringStripper.cpp
+++ b/toolkit/components/antitracking/URLQueryStringStripper.cpp
@@ -17,6 +17,7 @@
#include "nsIURIMutator.h"
#include "nsUnicharUtils.h"
#include "nsURLHelper.h"
+#include "nsNetUtil.h"
#include "mozilla/dom/StripOnShareRuleBinding.h"
namespace {
@@ -84,64 +85,16 @@ URLQueryStringStripper::StripForCopyOrShare(nsIURI* aURI,
NS_ENSURE_ARG_POINTER(strippedURI);
int aStripCount = 0;
- nsAutoCString query;
- nsresult rv = aURI->GetQuery(query);
- NS_ENSURE_SUCCESS(rv, rv);
- // We don't need to do anything if there is no query string.
- if (query.IsEmpty()) {
- Telemetry::Accumulate(Telemetry::STRIP_ON_SHARE_PARAMS_REMOVED, 0);
- return NS_OK;
- }
- nsAutoCString host;
- rv = aURI->GetHost(host);
+ nsresult rv =
+ StripForCopyOrShareInternal(aURI, strippedURI, aStripCount, false);
NS_ENSURE_SUCCESS(rv, rv);
- URLParams params;
-
- URLParams::Parse(query, true, [&](nsString&& name, nsString&& value) {
- nsAutoString lowerCaseName;
- ToLowerCase(name, lowerCaseName);
- // Look through the global rules.
- dom::StripRule globalRule;
- bool keyExists = mStripOnShareMap.Get("*"_ns, &globalRule);
- // There should always be a global rule.
- MOZ_ASSERT(keyExists);
- for (const auto& param : globalRule.mQueryParams) {
- if (param == lowerCaseName) {
- aStripCount++;
- return true;
- }
- }
-
- // Check for site specific rules.
- dom::StripRule siteSpecificRule;
- keyExists = mStripOnShareMap.Get(host, &siteSpecificRule);
- if (keyExists) {
- for (const auto& param : siteSpecificRule.mQueryParams) {
- if (param == lowerCaseName) {
- aStripCount++;
- return true;
- }
- }
- }
-
- params.Append(name, value);
- return true;
- });
-
Telemetry::Accumulate(Telemetry::STRIP_ON_SHARE_PARAMS_REMOVED, aStripCount);
if (!aStripCount) {
return NS_OK;
}
- nsAutoString newQuery;
- params.Serialize(newQuery, false);
-
- Unused << NS_MutateURI(aURI)
- .SetQuery(NS_ConvertUTF16toUTF8(newQuery))
- .Finalize(strippedURI);
-
// To calculate difference in length of the URL
// after stripping occurs for Telemetry
nsAutoCString specOriginalURI;
@@ -308,9 +261,8 @@ nsresult URLQueryStringStripper::StripQueryString(nsIURI* aURI,
URLParams params;
- URLParams::Parse(query, false, [&](nsString&& name, nsString&& value) {
- nsAutoString lowerCaseName;
-
+ URLParams::Parse(query, false, [&](nsCString&& name, nsCString&& value) {
+ nsAutoCString lowerCaseName;
ToLowerCase(name, lowerCaseName);
if (mList.Contains(lowerCaseName)) {
@@ -320,7 +272,7 @@ nsresult URLQueryStringStripper::StripQueryString(nsIURI* aURI,
// 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);
+ telemetryLabel.Append(lowerCaseName);
Telemetry::AccumulateCategorical(
Telemetry::QUERY_STRIPPING_COUNT_BY_PARAM, telemetryLabel);
@@ -336,13 +288,10 @@ nsresult URLQueryStringStripper::StripQueryString(nsIURI* aURI,
return NS_OK;
}
- nsAutoString newQuery;
+ nsAutoCString newQuery;
params.Serialize(newQuery, false);
- Unused << NS_MutateURI(uri)
- .SetQuery(NS_ConvertUTF16toUTF8(newQuery))
- .Finalize(aOutput);
-
+ Unused << NS_MutateURI(uri).SetQuery(newQuery).Finalize(aOutput);
return NS_OK;
}
@@ -362,10 +311,10 @@ bool URLQueryStringStripper::CheckAllowList(nsIURI* aURI) {
return mAllowList.Contains(baseDomain);
}
-void URLQueryStringStripper::PopulateStripList(const nsAString& aList) {
+void URLQueryStringStripper::PopulateStripList(const nsACString& aList) {
mList.Clear();
- for (const nsAString& item : aList.Split(' ')) {
+ for (const nsACString& item : aList.Split(' ')) {
mList.Insert(item);
}
}
@@ -380,7 +329,7 @@ void URLQueryStringStripper::PopulateAllowList(const nsACString& aList) {
NS_IMETHODIMP
URLQueryStringStripper::OnQueryStrippingListUpdate(
- const nsAString& aStripList, const nsACString& aAllowList) {
+ const nsACString& aStripList, const nsACString& aAllowList) {
PopulateStripList(aStripList);
PopulateAllowList(aAllowList);
return NS_OK;
@@ -396,8 +345,7 @@ URLQueryStringStripper::OnStripOnShareUpdate(const nsTArray<nsString>& aArgs,
continue;
}
for (const auto& topLevelSite : rule.mTopLevelSites) {
- mStripOnShareMap.InsertOrUpdate(NS_ConvertUTF16toUTF8(topLevelSite),
- rule);
+ mStripOnShareMap.InsertOrUpdate(topLevelSite, rule);
}
}
return NS_OK;
@@ -407,10 +355,9 @@ NS_IMETHODIMP
URLQueryStringStripper::TestGetStripList(nsACString& aStripList) {
aStripList.Truncate();
- StringJoinAppend(aStripList, " "_ns, mList,
- [](auto& aResult, const auto& aValue) {
- aResult.Append(NS_ConvertUTF16toUTF8(aValue));
- });
+ StringJoinAppend(
+ aStripList, " "_ns, mList,
+ [](auto& aResult, const auto& aValue) { aResult.Append(aValue); });
return NS_OK;
}
@@ -426,4 +373,110 @@ URLQueryStringStripper::Observe(nsISupports*, const char* aTopic,
return NS_OK;
}
+nsresult URLQueryStringStripper::StripForCopyOrShareInternal(
+ nsIURI* aURI, nsIURI** strippedURI, int& aStripCount,
+ bool aStripNestedURIs) {
+ nsAutoCString query;
+ nsresult rv = aURI->GetQuery(query);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // We don't need to do anything if there is no query string.
+ if (query.IsEmpty()) {
+ Telemetry::Accumulate(Telemetry::STRIP_ON_SHARE_PARAMS_REMOVED, 0);
+ return NS_OK;
+ }
+
+ nsAutoCString host;
+ rv = aURI->GetHost(host);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ URLParams params;
+
+ URLParams::Parse(query, false, [&](nsCString&& name, nsCString&& value) {
+ nsAutoCString lowerCaseName;
+ ToLowerCase(name, lowerCaseName);
+
+ // Look through the global rules.
+ dom::StripRule globalRule;
+ bool keyExists = mStripOnShareMap.Get("*"_ns, &globalRule);
+ // There should always be a global rule.
+ MOZ_ASSERT(keyExists);
+
+ // Look through the global rules.
+ for (const auto& param : globalRule.mQueryParams) {
+ if (param == lowerCaseName) {
+ aStripCount++;
+ return true;
+ }
+ }
+
+ // Check for site specific rules.
+ dom::StripRule siteSpecificRule;
+ keyExists = mStripOnShareMap.Get(host, &siteSpecificRule);
+ if (keyExists) {
+ for (const auto& param : siteSpecificRule.mQueryParams) {
+ if (param == lowerCaseName) {
+ aStripCount++;
+ return true;
+ }
+ }
+ }
+
+ // Only if it is top layer of the recursion then it
+ // checks if the value of the query parameter is a valid URI
+ // if not then it gets added back to the query, if it is then
+ // it gets passed back into this method but with the recursive
+ // stripping flag set to true
+ if (!aStripNestedURIs) {
+ nsAutoCString decodeValue;
+ URLParams::DecodeString(value, decodeValue);
+
+ nsCOMPtr<nsIURI> nestedURI;
+ rv = NS_NewURI(getter_AddRefs(nestedURI), decodeValue);
+
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ params.Append(name, value);
+ return true;
+ }
+
+ nsCOMPtr<nsIURI> strippedNestedURI;
+ rv = StripForCopyOrShareInternal(
+ nestedURI, getter_AddRefs(strippedNestedURI), aStripCount, true);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return false;
+ }
+
+ if (!strippedNestedURI) {
+ params.Append(name, value);
+ return true;
+ }
+
+ nsAutoCString nestedURIString;
+ rv = strippedNestedURI->GetSpec(nestedURIString);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return false;
+ }
+
+ // Encodes URI
+ nsAutoCString encodedURI;
+ URLParams::SerializeString(nestedURIString, encodedURI);
+
+ params.Append(name, encodedURI);
+ return true;
+ }
+
+ params.Append(name, value);
+ return true;
+ });
+
+ // Returns null for strippedURI if no query params have been stripped.
+ if (!aStripCount) {
+ return NS_OK;
+ }
+
+ nsAutoCString newQuery;
+ params.Serialize(newQuery, false);
+ return NS_MutateURI(aURI).SetQuery(newQuery).Finalize(strippedURI);
+}
+
} // namespace mozilla
diff --git a/toolkit/components/antitracking/URLQueryStringStripper.h b/toolkit/components/antitracking/URLQueryStringStripper.h
index 89466cfd12..3e8e8203a9 100644
--- a/toolkit/components/antitracking/URLQueryStringStripper.h
+++ b/toolkit/components/antitracking/URLQueryStringStripper.h
@@ -46,10 +46,16 @@ class URLQueryStringStripper final : public nsIObserver,
bool CheckAllowList(nsIURI* aURI);
- void PopulateStripList(const nsAString& aList);
+ void PopulateStripList(const nsACString& aList);
void PopulateAllowList(const nsACString& aList);
- nsTHashSet<nsString> mList;
+ // Recursive helper function that helps strip URIs of tracking parameters
+ // and enables the stripping of tracking paramerters that are in a URI which
+ // is nested in a query parameter
+ nsresult StripForCopyOrShareInternal(nsIURI* aURI, nsIURI** strippedURI,
+ int& aStripCount, bool aStripNestedURIs);
+
+ nsTHashSet<nsCString> mList;
nsTHashSet<nsCString> mAllowList;
nsCOMPtr<nsIURLQueryStrippingListService> mListService;
nsTHashMap<nsCString, dom::StripRule> mStripOnShareMap;
diff --git a/toolkit/components/antitracking/URLQueryStrippingListService.sys.mjs b/toolkit/components/antitracking/URLQueryStrippingListService.sys.mjs
index baaa9f3824..d9c1995821 100644
--- a/toolkit/components/antitracking/URLQueryStrippingListService.sys.mjs
+++ b/toolkit/components/antitracking/URLQueryStrippingListService.sys.mjs
@@ -31,10 +31,9 @@ XPCOMUtils.defineLazyPreferenceGetter(
PREF_STRIP_IS_TEST
);
-// Lazy getter for the strip-on-share strip list.
-ChromeUtils.defineLazyGetter(lazy, "StripOnShareList", async () => {
+async function fetchAndParseList(fileName) {
let response = await fetch(
- "chrome://global/content/antitracking/StripOnShare.json"
+ "chrome://global/content/antitracking/" + fileName
);
if (!response.ok) {
lazy.logger.error(
@@ -44,7 +43,48 @@ ChromeUtils.defineLazyGetter(lazy, "StripOnShareList", async () => {
"Error fetching strip-on-share strip list" + response.status
);
}
- return response.json();
+ return await response.json();
+}
+
+// Lazy getter for the strip-on-share strip list.
+ChromeUtils.defineLazyGetter(lazy, "StripOnShareList", async () => {
+ let [stripOnShareList, stripOnShareLGPLParams] = await Promise.all([
+ fetchAndParseList("StripOnShare.json"),
+ fetchAndParseList("StripOnShareLGPL.json"),
+ ]);
+
+ if (!stripOnShareList || !stripOnShareLGPLParams) {
+ lazy.logger.error("Error strip-on-share strip list were not loaded");
+ throw new Error("Error fetching strip-on-share strip list were not loaded");
+ }
+
+ // Combines the mozilla licensed strip on share param
+ // list and the LGPL licensed strip on share param list
+ for (const key in stripOnShareLGPLParams) {
+ if (Object.hasOwn(stripOnShareList, key)) {
+ stripOnShareList[key].queryParams.push(
+ ...stripOnShareLGPLParams[key].queryParams
+ );
+
+ stripOnShareList[key].topLevelSites.push(
+ ...stripOnShareLGPLParams[key].topLevelSites
+ );
+
+ // Removes duplicates topLevelSitres
+ stripOnShareList[key].topLevelSites = [
+ ...new Set(stripOnShareList[key].topLevelSites),
+ ];
+
+ // Removes duplicates queryParams
+ stripOnShareList[key].queryParams = [
+ ...new Set(stripOnShareList[key].queryParams),
+ ];
+ } else {
+ stripOnShareList[key] = stripOnShareLGPLParams[key];
+ }
+ }
+
+ return stripOnShareList;
});
export class URLQueryStrippingListService {
@@ -142,11 +182,11 @@ export class URLQueryStrippingListService {
}
// Get the list from pref.
- this._onPrefUpdate(
+ await this._onPrefUpdate(
PREF_STRIP_LIST_NAME,
Services.prefs.getStringPref(PREF_STRIP_LIST_NAME, "")
);
- this._onPrefUpdate(
+ await this._onPrefUpdate(
PREF_ALLOW_LIST_NAME,
Services.prefs.getStringPref(PREF_ALLOW_LIST_NAME, "")
);
@@ -219,7 +259,7 @@ export class URLQueryStrippingListService {
this._notifyObservers();
}
- _onPrefUpdate(pref, value) {
+ async _onPrefUpdate(pref, value) {
switch (pref) {
case PREF_STRIP_LIST_NAME:
this.prefStripList = new Set(value ? value.split(" ") : []);
@@ -235,7 +275,7 @@ export class URLQueryStrippingListService {
}
this._notifyObservers();
- this._notifyStripOnShareObservers();
+ await this._notifyStripOnShareObservers();
}
_getListFromSharedData() {
diff --git a/toolkit/components/antitracking/jar.mn b/toolkit/components/antitracking/jar.mn
index e45b37c5b6..2f8c4d7ee4 100644
--- a/toolkit/components/antitracking/jar.mn
+++ b/toolkit/components/antitracking/jar.mn
@@ -9,4 +9,7 @@ toolkit.jar:
# domain1: {queryParams: [param1, param2, ..], topLevelSites: [www.site.de, www.site.com,...]}, domain2: {...}
# This list will be consumed from the nsIQueryStrippingListService and
# later be dispatched to the nsIURLQueryStringStripper in a further processed form.
- content/global/antitracking/StripOnShare.json (data/StripOnShare.json)
+ content/global/antitracking/StripOnShare.json (StripOnShareLists/MPL2/StripOnShare.json)
+
+ # Separate StripOnShare list for parameters that are covered in the LGPL License
+ content/global/antitracking/StripOnShareLGPL.json (StripOnShareLists/LGPL/StripOnShareLGPL.json)
diff --git a/toolkit/components/antitracking/nsIURLQueryStringStripper.idl b/toolkit/components/antitracking/nsIURLQueryStringStripper.idl
index 372cc0f94a..b3e939094b 100644
--- a/toolkit/components/antitracking/nsIURLQueryStringStripper.idl
+++ b/toolkit/components/antitracking/nsIURLQueryStringStripper.idl
@@ -23,7 +23,7 @@ interface nsIURLQueryStringStripper : nsISupports {
// Strip the query parameters that are in the strip list. Return the amount of
// query parameters that have been stripped. Returns 0 if no query parameters
// have been stripped or the feature is disabled.
- uint32_t strip(in nsIURI aURI, in bool aIsPBM, out nsIURI aOutput);
+ uint32_t strip(in nsIURI aURI, in boolean aIsPBM, out nsIURI aOutput);
// Strip the query parameters that are in the stripForCopy/Share strip list.
// Returns ether the stripped URI or null if no query parameters have been stripped
diff --git a/toolkit/components/antitracking/nsIURLQueryStrippingListService.idl b/toolkit/components/antitracking/nsIURLQueryStrippingListService.idl
index f746126c13..1af2c4727f 100644
--- a/toolkit/components/antitracking/nsIURLQueryStrippingListService.idl
+++ b/toolkit/components/antitracking/nsIURLQueryStrippingListService.idl
@@ -22,7 +22,7 @@ interface nsIURLQueryStrippingListObserver : nsISupports
* A comma-separated list of hosts (eTLD+1) that are exempt from query
* stripping.
*/
- void onQueryStrippingListUpdate(in AString aStripList, in ACString aAllowList);
+ void onQueryStrippingListUpdate(in ACString aStripList, in ACString aAllowList);
/**
* Called by nsIQueryStrippingListService when the list of query stripping
diff --git a/toolkit/components/antitracking/test/browser/browser.toml b/toolkit/components/antitracking/test/browser/browser.toml
index 9d0874ed3a..edb429b49e 100644
--- a/toolkit/components/antitracking/test/browser/browser.toml
+++ b/toolkit/components/antitracking/test/browser/browser.toml
@@ -1,5 +1,9 @@
[DEFAULT]
-skip-if = ["os == 'linux' && (asan || tsan)"] # bug 1662229 - task exception
+skip-if = [
+ "os == 'linux' && os_version == '18.04' && asan", # bug 1662229 - task exception
+ "os == 'linux' && os_version == '18.04' && tsan", # bug 1662229 - task exception
+ "debug", # bug 1884982 - takes 20+ minutes to run on debug
+]
prefs = [
"dom.storage_access.prompt.testing=true", # Disable the Storage Access API prompts for all of the tests in this directory
"dom.storage_access.prompt.testing.allow=true",
@@ -108,6 +112,8 @@ skip-if = ["os == 'mac' && !debug"] # Bug 1503778, 1577362
["browser_onModifyRequestNotificationForTrackingResources.js"]
+["browser_partitionedABA.js"]
+
["browser_partitionedClearSiteDataHeader.js"]
support-files = ["clearSiteData.sjs"]
@@ -194,7 +200,7 @@ support-files = [
"!/browser/components/originattributes/test/browser/file_thirdPartyChild.request.html",
"!/browser/components/originattributes/test/browser/file_thirdPartyChild.script.js",
"!/browser/components/originattributes/test/browser/file_thirdPartyChild.sharedworker.js",
- "!/browser/components/originattributes/test/browser/file_thirdPartyChild.video.ogv",
+ "!/browser/components/originattributes/test/browser/file_thirdPartyChild.video.webm",
"!/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.fetch.html",
"!/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.js",
"!/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.request.html",
@@ -210,7 +216,7 @@ support-files = [
"file_saveAsImage.sjs",
"file_saveAsVideo.sjs",
"file_saveAsPageInfo.html",
- "file_video.ogv",
+ "file_video.webm",
]
["browser_staticPartition_tls_session.js"]
diff --git a/toolkit/components/antitracking/test/browser/browser_doublyNestedTracker.js b/toolkit/components/antitracking/test/browser/browser_doublyNestedTracker.js
index 4f38b29a7d..c3b6342ce1 100644
--- a/toolkit/components/antitracking/test/browser/browser_doublyNestedTracker.js
+++ b/toolkit/components/antitracking/test/browser/browser_doublyNestedTracker.js
@@ -36,7 +36,7 @@ add_task(async function () {
async function runChecks() {
is(document.cookie, "", "No cookies for me");
document.cookie = "name=value";
- is(document.cookie, "name=value", "I have the cookies!");
+ is(document.cookie, "", "I don't have the cookies!");
}
await new Promise(resolve => {
diff --git a/toolkit/components/antitracking/test/browser/browser_partitionedABA.js b/toolkit/components/antitracking/test/browser/browser_partitionedABA.js
new file mode 100644
index 0000000000..b6acc82d48
--- /dev/null
+++ b/toolkit/components/antitracking/test/browser/browser_partitionedABA.js
@@ -0,0 +1,86 @@
+/* vim: set ts=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/. */
+
+/*
+ * A test to verify that ABA iframes partition at least localStorage and document.cookie
+ */
+
+"use strict";
+
+add_setup(async function () {
+ await setCookieBehaviorPref(
+ BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
+ false
+ );
+});
+
+add_task(async function runTest() {
+ info("Creating the tab");
+ let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
+ gBrowser.selectedTab = tab;
+
+ let browser = tab.linkedBrowser;
+ await BrowserTestUtils.browserLoaded(browser);
+
+ info("Creating the third-party iframe");
+ let ifrBC = await SpecialPowers.spawn(
+ browser,
+ [TEST_TOP_PAGE_7],
+ async page => {
+ let ifr = content.document.createElement("iframe");
+
+ let loading = ContentTaskUtils.waitForEvent(ifr, "load");
+ content.document.body.appendChild(ifr);
+ ifr.src = page;
+ await loading;
+
+ return ifr.browsingContext;
+ }
+ );
+
+ info("Creating the ABA iframe");
+ let ifrABABC = await SpecialPowers.spawn(
+ ifrBC,
+ [TEST_TOP_PAGE],
+ async page => {
+ let ifr = content.document.createElement("iframe");
+
+ let loading = ContentTaskUtils.waitForEvent(ifr, "load");
+ content.document.body.appendChild(ifr);
+ ifr.src = page;
+ await loading;
+
+ return ifr.browsingContext;
+ }
+ );
+
+ info("Write cookie to the ABA third-party iframe");
+ await SpecialPowers.spawn(ifrABABC, [], async _ => {
+ content.document.cookie = "foo; SameSite=None; Secure; Partitioned";
+ });
+
+ let cookie = await SpecialPowers.spawn(browser, [], async () => {
+ return content.document.cookie;
+ });
+ is(cookie, "", "Cookie is not in the top level");
+
+ info("Write localstorage to the ABA third-party iframe");
+ await SpecialPowers.spawn(ifrABABC, [], async _ => {
+ content.localStorage.setItem("foo", "bar");
+ });
+
+ let storage = await SpecialPowers.spawn(browser, [], async () => {
+ return content.localStorage.getItem("foo");
+ });
+ is(storage, null, "LocalStorage update is not in the top level");
+
+ info("Clean up");
+ BrowserTestUtils.removeTab(tab);
+ await new Promise(resolve => {
+ Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
+ resolve()
+ );
+ });
+});
diff --git a/toolkit/components/antitracking/test/browser/browser_staticPartition_cache.js b/toolkit/components/antitracking/test/browser/browser_staticPartition_cache.js
index 9afe3180fb..9383e5a6f9 100644
--- a/toolkit/components/antitracking/test/browser/browser_staticPartition_cache.js
+++ b/toolkit/components/antitracking/test/browser/browser_staticPartition_cache.js
@@ -105,7 +105,7 @@ add_task(async function () {
// The CSS cache needs to be cleared in-process.
content.windowUtils.clearSharedStyleSheetCache();
- let videoURL = arg.urlPrefix + "file_thirdPartyChild.video.ogv";
+ let videoURL = arg.urlPrefix + "file_thirdPartyChild.video.webm";
let audioURL = arg.urlPrefix + "file_thirdPartyChild.audio.ogg";
let URLSuffix = "?r=" + arg.randomSuffix;
@@ -176,7 +176,7 @@ add_task(async function () {
"xhr.html",
"worker.xhr.html",
"audio.ogg",
- "video.ogv",
+ "video.webm",
"fetch.html",
"worker.fetch.html",
"request.html",
diff --git a/toolkit/components/antitracking/test/browser/browser_staticPartition_saveAs.js b/toolkit/components/antitracking/test/browser/browser_staticPartition_saveAs.js
index b9984829eb..9da751cadb 100644
--- a/toolkit/components/antitracking/test/browser/browser_staticPartition_saveAs.js
+++ b/toolkit/components/antitracking/test/browser/browser_staticPartition_saveAs.js
@@ -401,7 +401,7 @@ add_task(async function testPageInfoMediaSaveAs() {
);
info("Open the media panel of the pageinfo.");
- let pageInfo = BrowserPageInfo(
+ let pageInfo = BrowserCommands.pageInfo(
gBrowser.selectedBrowser.currentURI.spec,
"mediaTab"
);
@@ -478,7 +478,7 @@ add_task(async function testPageInfoMediaMultipleSelectedSaveAs() {
);
info("Open the media panel of the pageinfo.");
- let pageInfo = BrowserPageInfo(
+ let pageInfo = BrowserCommands.pageInfo(
gBrowser.selectedBrowser.currentURI.spec,
"mediaTab"
);
diff --git a/toolkit/components/antitracking/test/browser/browser_storageAccessThirdPartyChecks_alwaysPartition.js b/toolkit/components/antitracking/test/browser/browser_storageAccessThirdPartyChecks_alwaysPartition.js
index f31c7893d0..8ea97dac68 100644
--- a/toolkit/components/antitracking/test/browser/browser_storageAccessThirdPartyChecks_alwaysPartition.js
+++ b/toolkit/components/antitracking/test/browser/browser_storageAccessThirdPartyChecks_alwaysPartition.js
@@ -53,6 +53,7 @@ AntiTracking._createTask({
"https://tracking.example.org",
"https://tracking.example.org",
"https://tracking.example.org",
+ "https://another-tracking.example.net",
"https://itisatracker.org",
],
});
diff --git a/toolkit/components/antitracking/test/browser/file_saveAsPageInfo.html b/toolkit/components/antitracking/test/browser/file_saveAsPageInfo.html
index aa3de2a555..c8c409d130 100644
--- a/toolkit/components/antitracking/test/browser/file_saveAsPageInfo.html
+++ b/toolkit/components/antitracking/test/browser/file_saveAsPageInfo.html
@@ -1,6 +1,6 @@
<html>
<body>
<img src="http://example.net/browser/toolkit/components/antitracking/test/browser/raptor.jpg" id="image1">
- <video src="http://example.net/browser/toolkit/components/antitracking/test/browser/file_video.ogv" id="video1"> </video>
+ <video src="http://example.net/browser/toolkit/components/antitracking/test/browser/file_video.webm" id="video1"> </video>
</body>
</html>
diff --git a/toolkit/components/antitracking/test/browser/file_video.ogv b/toolkit/components/antitracking/test/browser/file_video.ogv
deleted file mode 100644
index 68dee3cf2b..0000000000
--- a/toolkit/components/antitracking/test/browser/file_video.ogv
+++ /dev/null
Binary files differ
diff --git a/toolkit/components/antitracking/test/browser/file_video.webm b/toolkit/components/antitracking/test/browser/file_video.webm
new file mode 100644
index 0000000000..2cee5a9e51
--- /dev/null
+++ b/toolkit/components/antitracking/test/browser/file_video.webm
Binary files differ
diff --git a/toolkit/components/antitracking/test/gtest/TestStoragePrincipalHelper.cpp b/toolkit/components/antitracking/test/gtest/TestStoragePrincipalHelper.cpp
index 44959e4dc8..666757c382 100644
--- a/toolkit/components/antitracking/test/gtest/TestStoragePrincipalHelper.cpp
+++ b/toolkit/components/antitracking/test/gtest/TestStoragePrincipalHelper.cpp
@@ -45,7 +45,7 @@ nsresult CreateMockChannel(nsIPrincipal* aPrincipal, bool isThirdParty,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadInfo> mockLoadInfo = mockChannel->LoadInfo();
- rv = mockLoadInfo->SetIsThirdPartyContextToTopWindow(isThirdParty);
+ rv = mockLoadInfo->SetIsInThirdPartyContext(isThirdParty);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsICookieJarSettings> cjs;
diff --git a/toolkit/components/antitracking/test/xpcshell/test_validate_strip_on_share_list.js b/toolkit/components/antitracking/test/xpcshell/test_validate_strip_on_share_list.js
index 48a0bd4682..f8be5fccad 100644
--- a/toolkit/components/antitracking/test/xpcshell/test_validate_strip_on_share_list.js
+++ b/toolkit/components/antitracking/test/xpcshell/test_validate_strip_on_share_list.js
@@ -7,67 +7,19 @@ const { JsonSchema } = ChromeUtils.importESModule(
"resource://gre/modules/JsonSchema.sys.mjs"
);
-let stripOnShareList;
+let stripOnShareMergedList, stripOnShareLGPLParams, stripOnShareList;
-// Fetching strip on share list
-add_setup(async function () {
- /* globals fetch */
- let response = await fetch(
- "chrome://global/content/antitracking/StripOnShare.json"
- );
+async function fetchAndParseList(fileName) {
+ let response = await fetch("chrome://global/content/" + fileName);
if (!response.ok) {
throw new Error(
"Error fetching strip-on-share strip list" + response.status
);
}
- stripOnShareList = await response.json();
-});
-
-// Check if the Strip on Share list contains any duplicate params
-add_task(async function test_check_duplicates() {
- let stripOnShareParams = stripOnShareList;
-
- const allQueryParams = [];
-
- for (const domain in stripOnShareParams) {
- for (let param in stripOnShareParams[domain].queryParams) {
- allQueryParams.push(stripOnShareParams[domain].queryParams[param]);
- }
- }
-
- let setOfParams = new Set(allQueryParams);
-
- if (setOfParams.size != allQueryParams.length) {
- let setToCheckDupes = new Set();
- let dupeList = new Set();
- for (const domain in stripOnShareParams) {
- for (let param in stripOnShareParams[domain].queryParams) {
- let tempParam = stripOnShareParams[domain].queryParams[param];
-
- if (setToCheckDupes.has(tempParam)) {
- dupeList.add(tempParam);
- } else {
- setToCheckDupes.add(tempParam);
- }
- }
- }
-
- Assert.equal(
- setOfParams.size,
- allQueryParams.length,
- "There are duplicates rules. The duplicate rules are " + [...dupeList]
- );
- }
+ return await response.json();
+}
- Assert.equal(
- setOfParams.size,
- allQueryParams.length,
- "There are no duplicates rules."
- );
-});
-
-// Validate the format of Strip on Share list with Schema
-add_task(async function test_check_schema() {
+async function validateSchema(paramList, nameOfList) {
let schema = {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
@@ -88,13 +40,86 @@ add_task(async function test_check_schema() {
required: ["global"],
};
- let stripOnShareParams = stripOnShareList;
let validator = new JsonSchema.Validator(schema);
- let { valid, errors } = validator.validate(stripOnShareParams);
+ let { valid, errors } = validator.validate(paramList);
if (!valid) {
- info("validation errors: " + JSON.stringify(errors, null, 2));
+ info(
+ nameOfList +
+ " JSON contains these validation errors: " +
+ JSON.stringify(errors, null, 2)
+ );
+ }
+
+ Assert.ok(valid, nameOfList + " JSON is valid");
+}
+
+// Fetching strip on share list
+add_setup(async function () {
+ /* globals fetch */
+
+ [stripOnShareList, stripOnShareLGPLParams] = await Promise.all([
+ fetchAndParseList("antitracking/StripOnShare.json"),
+ fetchAndParseList("antitracking/StripOnShareLGPL.json"),
+ ]);
+
+ stripOnShareMergedList = stripOnShareList;
+
+ // Combines the mozilla licensed strip on share param
+ // list and the LGPL licensed strip on share param list
+ for (const key in stripOnShareLGPLParams) {
+ if (Object.hasOwn(stripOnShareMergedList, key)) {
+ stripOnShareMergedList[key].queryParams.push(
+ ...stripOnShareLGPLParams[key].queryParams
+ );
+ } else {
+ stripOnShareMergedList[key] = stripOnShareLGPLParams[key];
+ }
+ }
+});
+
+// Check if the Strip on Share list contains any duplicate params
+add_task(async function test_check_duplicates() {
+ for (const domain in stripOnShareMergedList) {
+ // Creates a set of query parameters for a given domain to check
+ // for duplicates
+ let setOfParams = new Set(stripOnShareMergedList[domain].queryParams);
+
+ // If there are duplicates which is known because the sizes of the set
+ // and array don't match, then we check which parameters are duplciates
+ if (setOfParams.size != stripOnShareMergedList[domain].queryParams.length) {
+ let setToCheckDupes = new Set();
+ let dupeList = new Set();
+ for (let param in stripOnShareMergedList[domain].queryParams) {
+ let tempParam = stripOnShareMergedList[domain].queryParams[param];
+
+ if (setToCheckDupes.has(tempParam)) {
+ dupeList.add(tempParam);
+ } else {
+ setToCheckDupes.add(tempParam);
+ }
+ }
+
+ Assert.equal(
+ setOfParams.size,
+ stripOnShareMergedList[domain].queryParams.length,
+ "There are duplicates rules in " +
+ domain +
+ ". The duplicate rules are " +
+ [...dupeList]
+ );
+ }
+
+ Assert.equal(
+ setOfParams.size,
+ stripOnShareMergedList[domain].queryParams.length,
+ "There are no duplicates rules."
+ );
}
+});
- Assert.ok(valid, "Strip on share JSON is valid");
+// Validate the format of Strip on Share list with Schema
+add_task(async function test_check_schema() {
+ validateSchema(stripOnShareLGPLParams, "Strip On Share LGPL");
+ validateSchema(stripOnShareList, "Strip On Share");
});