Backed out 3 changesets (bug 1884941, bug 1877419) for causing bustage in URLQueryStringStripper.cpp CLOSED TREE

Backed out changeset 32c74a4cd05b (bug 1877419)
Backed out changeset c2ca2f596c09 (bug 1877419)
Backed out changeset 45931e6db21e (bug 1884941)
This commit is contained in:
Noemi Erli 2024-03-25 21:50:27 +02:00
Родитель 7ccbaae0d9
Коммит 18b56b463a
12 изменённых файлов: 88 добавлений и 310 удалений

Просмотреть файл

@ -86,8 +86,6 @@ skip-if = ["os == 'linux' && socketprocess_networking"]
["browser_strip_on_share_link.js"]
["browser_strip_on_share_nested_link.js"]
["browser_utilityOverlay.js"]
https_first_disabled = true
skip-if = ["os == 'linux' && socketprocess_networking"]

Просмотреть файл

@ -1,152 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let listService;
const TEST_URL =
"https://example.com/browser/browser/base/content/test/general/dummy_page.html";
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [["privacy.query_stripping.strip_list", "stripParam"]],
});
// Get the list service so we can wait for it to be fully initialized before running tests.
listService = Cc["@mozilla.org/query-stripping-list-service;1"].getService(
Ci.nsIURLQueryStrippingListService
);
await listService.testWaitForInit();
});
/*
Tests the strip-on-share feature for in-content links with nested urls
*/
// Testing nested stripping with global params
add_task(async function testNestedStrippingGlobalParam() {
let validUrl =
"https://www.example.com/?test=https%3A%2F%2Fwww.example.net%2F%3Futm_ad%3D1234";
let shortenedUrl =
"https://www.example.com/?test=https%3A%2F%2Fwww.example.net%2F";
await testStripOnShare({
originalURI: validUrl,
strippedURI: shortenedUrl,
});
});
// Testing nested stripping with site specific params
add_task(async function testNestedStrippingSiteSpecific() {
let validUrl =
"https://www.example.com/?test=https%3A%2F%2Fwww.example.net%2F%3Ftest_3%3D1234";
let shortenedUrl =
"https://www.example.com/?test=https%3A%2F%2Fwww.example.net%2F";
await testStripOnShare({
originalURI: validUrl,
strippedURI: shortenedUrl,
});
});
// Testing nested stripping with incorrect site specific params
add_task(async function testNoStrippedNestedParam() {
let validUrl =
"https://www.example.com/?test=https%3A%2F%2Fwww.example.com%2F%3Ftest_3%3D1234";
let shortenedUrl =
"https://www.example.com/?test=https%3A%2F%2Fwww.example.com%2F%3Ftest_3%3D1234";
await testStripOnShare({
originalURI: validUrl,
strippedURI: shortenedUrl,
});
});
// Testing order of stripping for nested stripping
add_task(async function testOrderOfStripping() {
let validUrl =
"https://www.example.com/?test_1=https%3A%2F%2Fwww.example.net%2F%3Ftest_3%3D1234";
let shortenedUrl = "https://www.example.com/";
await testStripOnShare({
originalURI: validUrl,
strippedURI: shortenedUrl,
});
});
// Testing correct scoping of site specific params for nested stripping
add_task(async function testMultipleQueryParamsWithNestedStripping() {
let validUrl =
"https://www.example.com/?test_3=1234&test=https%3A%2F%2Fwww.example.net%2F%3Ftest_3%3D1234";
let shortenedUrl =
"https://www.example.com/?test_3=1234&test=https%3A%2F%2Fwww.example.net%2F";
await testStripOnShare({
originalURI: validUrl,
strippedURI: shortenedUrl,
});
});
/**
* Opens a new tab, opens the context menu and checks that the strip-on-share menu item is visible.
* Checks that the stripped version of the url is copied to the clipboard.
*
* @param {string} originalURI - The orginal url before the stripping occurs
* @param {string} strippedURI - The expected url after stripping occurs
*/
async function testStripOnShare({ originalURI, strippedURI }) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.query_stripping.strip_on_share.enabled", true],
["privacy.query_stripping.strip_on_share.enableTestMode", true],
],
});
let testJson = {
global: {
queryParams: ["utm_ad"],
topLevelSites: ["*"],
},
example: {
queryParams: ["test_2", "test_1"],
topLevelSites: ["www.example.com"],
},
exampleNet: {
queryParams: ["test_3", "test_4"],
topLevelSites: ["www.example.net"],
},
};
await listService.testSetList(testJson);
await BrowserTestUtils.withNewTab(TEST_URL, async function (browser) {
// Prepare a link
await SpecialPowers.spawn(browser, [originalURI], function (startingURI) {
let link = content.document.createElement("a");
link.href = startingURI;
link.textContent = "link with query param";
link.id = "link";
content.document.body.appendChild(link);
});
let contextMenu = document.getElementById("contentAreaContextMenu");
// Open the context menu
let awaitPopupShown = BrowserTestUtils.waitForEvent(
contextMenu,
"popupshown"
);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#link",
{ type: "contextmenu", button: 2 },
browser
);
await awaitPopupShown;
let awaitPopupHidden = BrowserTestUtils.waitForEvent(
contextMenu,
"popuphidden"
);
let stripOnShare = contextMenu.querySelector("#context-stripOnShareLink");
Assert.ok(BrowserTestUtils.isVisible(stripOnShare), "Menu item is visible");
// Make sure the stripped link will be copied to the clipboard
await SimpleTest.promiseClipboardChange(strippedURI, () => {
contextMenu.activateItem(stripOnShare);
});
await awaitPopupHidden;
});
}

Просмотреть файл

@ -324,7 +324,7 @@ bool OriginAttributes::PopulateFromSuffix(const nsACString& aStr) {
MOZ_RELEASE_ASSERT(mPartitionKey.IsEmpty());
return URLParams::Parse(
Substring(aStr, 1, aStr.Length() - 1), true,
Substring(aStr, 1, aStr.Length() - 1),
[this](const nsAString& aName, const nsAString& aValue) {
if (aName.EqualsLiteral("inBrowser")) {
if (!aValue.EqualsLiteral("1")) {

Просмотреть файл

@ -422,7 +422,7 @@ already_AddRefed<FormData> BodyUtil::ConsumeFormData(
if (isValidUrlEncodedMimeType) {
RefPtr<FormData> fd = new FormData(aParent);
DebugOnly<bool> status = URLParams::Parse(
aStr, true, [&fd](const nsAString& aName, const nsAString& aValue) {
aStr, [&fd](const nsAString& aName, const nsAString& aValue) {
ErrorResult rv;
fd->Append(aName, aValue, rv);
MOZ_ASSERT(!rv.Failed());

Просмотреть файл

@ -7658,7 +7658,7 @@ Result<bool, nsresult> UpgradeStorageFrom1_0To2_0Helper::MaybeRemoveAppsData(
MOZ_ASSERT(originalSuffix[0] == '^');
if (!URLParams::Parse(
Substring(originalSuffix, 1, originalSuffix.Length() - 1), true,
Substring(originalSuffix, 1, originalSuffix.Length() - 1),
[](const nsAString& aName, const nsAString& aValue) {
if (aName.EqualsLiteral("appId")) {
return false;

Просмотреть файл

@ -68,7 +68,7 @@ bool StorageOriginAttributes::PopulateFromSuffix(const nsACString& aStr) {
}
bool ok =
URLParams::Parse(Substring(aStr, 1, aStr.Length() - 1), true,
URLParams::Parse(Substring(aStr, 1, aStr.Length() - 1),
[this](const nsAString& aName, const nsAString& aValue) {
if (aName.EqualsLiteral("inBrowser")) {
if (!aValue.EqualsLiteral("1")) {

Просмотреть файл

@ -1236,8 +1236,8 @@ void URLParams::DecodeString(const nsACString& aInput, nsAString& aOutput) {
/* static */
bool URLParams::ParseNextInternal(const char*& aStart, const char* const aEnd,
bool aShouldDecode, nsAString* aOutputName,
nsAString* aOutputValue) {
nsAString* aOutDecodedName,
nsAString* aOutDecodedValue) {
nsDependentCSubstring string;
const char* const iter = std::find(aStart, aEnd, '&');
@ -1267,14 +1267,9 @@ bool URLParams::ParseNextInternal(const char*& aStart, const char* const aEnd,
name.Rebind(string, 0);
}
if (aShouldDecode) {
DecodeString(name, *aOutputName);
DecodeString(value, *aOutputValue);
return true;
}
DecodeString(name, *aOutDecodedName);
DecodeString(value, *aOutDecodedValue);
ConvertString(name, *aOutputName);
ConvertString(value, *aOutputValue);
return true;
}
@ -1283,7 +1278,7 @@ bool URLParams::Extract(const nsACString& aInput, const nsAString& aName,
nsAString& aValue) {
aValue.SetIsVoid(true);
return !URLParams::Parse(
aInput, true, [&aName, &aValue](const nsAString& name, nsString&& value) {
aInput, [&aName, &aValue](const nsAString& name, nsString&& value) {
if (aName == name) {
aValue = std::move(value);
return false;
@ -1296,13 +1291,15 @@ void URLParams::ParseInput(const nsACString& aInput) {
// Remove all the existing data before parsing a new input.
DeleteAll();
URLParams::Parse(aInput, true, [this](nsString&& name, nsString&& value) {
URLParams::Parse(aInput, [this](nsString&& name, nsString&& value) {
mParams.AppendElement(Param{std::move(name), std::move(value)});
return true;
});
}
void URLParams::SerializeString(const nsCString& aInput, nsAString& aValue) {
namespace {
void SerializeString(const nsCString& aInput, nsAString& aValue) {
const unsigned char* p = (const unsigned char*)aInput.get();
const unsigned char* end = p + aInput.Length();
@ -1323,6 +1320,8 @@ void URLParams::SerializeString(const nsCString& aInput, nsAString& aValue) {
}
}
} // namespace
void URLParams::Serialize(nsAString& aValue, bool aEncode) const {
aValue.Truncate();
bool first = true;

Просмотреть файл

@ -257,20 +257,19 @@ class URLParams final {
* true otherwise
*/
template <typename ParamHandler>
static bool Parse(const nsACString& aInput, bool aShouldDecode,
ParamHandler aParamHandler) {
static bool Parse(const nsACString& aInput, ParamHandler aParamHandler) {
const char* start = aInput.BeginReading();
const char* const end = aInput.EndReading();
while (start != end) {
nsAutoString name;
nsAutoString value;
nsAutoString decodedName;
nsAutoString decodedValue;
if (!ParseNextInternal(start, end, aShouldDecode, &name, &value)) {
if (!ParseNextInternal(start, end, &decodedName, &decodedValue)) {
continue;
}
if (!aParamHandler(std::move(name), std::move(value))) {
if (!aParamHandler(std::move(decodedName), std::move(decodedValue))) {
return false;
}
}
@ -308,8 +307,6 @@ class URLParams final {
*/
void Serialize(nsAString& aValue, bool aEncode) const;
static void SerializeString(const nsCString& aInput, nsAString& aValue);
void Get(const nsAString& aName, nsString& aRetval);
void GetAll(const nsAString& aName, nsTArray<nsString>& aRetval);
@ -340,8 +337,6 @@ class URLParams final {
uint32_t Length() const { return mParams.Length(); }
static void DecodeString(const nsACString& aInput, nsAString& aOutput);
const nsAString& GetKeyAtIndex(uint32_t aIndex) const {
MOZ_ASSERT(aIndex < mParams.Length());
return mParams[aIndex].mKey;
@ -359,10 +354,11 @@ class URLParams final {
void Sort();
private:
static void DecodeString(const nsACString& aInput, nsAString& aOutput);
static void ConvertString(const nsACString& aInput, nsAString& aOutput);
static bool ParseNextInternal(const char*& aStart, const char* aEnd,
bool aShouldDecode, nsAString* aOutputName,
nsAString* aOutputValue);
nsAString* aOutDecodedName,
nsAString* aOutDecodedValue);
struct Param {
nsString mKey;

Просмотреть файл

@ -1155,20 +1155,19 @@ nsresult Connection::initialize(nsIFileURL* aFileURL) {
bool hasKey = false;
bool hasDirectoryLockId = false;
MOZ_ALWAYS_TRUE(
URLParams::Parse(query, true,
[&hasKey, &hasDirectoryLockId](const nsAString& aName,
const nsAString& aValue) {
if (aName.EqualsLiteral("key")) {
hasKey = true;
return true;
}
if (aName.EqualsLiteral("directoryLockId")) {
hasDirectoryLockId = true;
return true;
}
return true;
}));
MOZ_ALWAYS_TRUE(URLParams::Parse(
query, [&hasKey, &hasDirectoryLockId](const nsAString& aName,
const nsAString& aValue) {
if (aName.EqualsLiteral("key")) {
hasKey = true;
return true;
}
if (aName.EqualsLiteral("directoryLockId")) {
hasDirectoryLockId = true;
return true;
}
return true;
}));
bool exclusive = StaticPrefs::storage_sqlite_exclusiveLock_enabled();

Просмотреть файл

@ -17,7 +17,6 @@
#include "nsIURIMutator.h"
#include "nsUnicharUtils.h"
#include "nsURLHelper.h"
#include "nsNetUtil.h"
#include "mozilla/dom/StripOnShareRuleBinding.h"
namespace {
@ -85,9 +84,50 @@ URLQueryStringStripper::StripForCopyOrShare(nsIURI* aURI,
NS_ENSURE_ARG_POINTER(strippedURI);
int aStripCount = 0;
nsresult rv =
StripForCopyOrShareInternal(aURI, strippedURI, aStripCount, false);
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, [&](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);
@ -95,6 +135,13 @@ URLQueryStringStripper::StripForCopyOrShare(nsIURI* aURI,
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;
@ -261,7 +308,7 @@ nsresult URLQueryStringStripper::StripQueryString(nsIURI* aURI,
URLParams params;
URLParams::Parse(query, false, [&](nsString&& name, nsString&& value) {
URLParams::Parse(query, [&](nsString&& name, nsString&& value) {
nsAutoString lowerCaseName;
ToLowerCase(name, lowerCaseName);
@ -379,107 +426,4 @@ 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, [&](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);
// 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) {
nsAutoString decodeValue;
URLParams::DecodeString(NS_ConvertUTF16toUTF8(value), decodeValue);
nsCOMPtr<nsIURI> nestedURI;
rv = NS_NewURI(getter_AddRefs(nestedURI), decodeValue);
if (NS_WARN_IF(NS_FAILED(rv))) {
if (rv == NS_ERROR_NOT_AVAILABLE) {
LOG(("Unable to obtain ioService"));
return false;
}
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;
}
nsAutoCString nestedURIString;
rv = strippedNestedURI->GetSpec(nestedURIString);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
// Encodes URI
nsAutoString encodedURI;
URLParams::SerializeString(nestedURIString, encodedURI);
params.Append(name, encodedURI);
return true;
}
params.Append(name, value);
return true;
});
nsAutoString newQuery;
params.Serialize(newQuery, false);
return NS_MutateURI(aURI)
.SetQuery(NS_ConvertUTF16toUTF8(newQuery))
.Finalize(strippedURI);
}
} // namespace mozilla

Просмотреть файл

@ -49,12 +49,6 @@ class URLQueryStringStripper final : public nsIObserver,
void PopulateStripList(const nsAString& aList);
void PopulateAllowList(const nsACString& aList);
// 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<nsString> mList;
nsTHashSet<nsCString> mAllowList;
nsCOMPtr<nsIURLQueryStrippingListService> mListService;

Просмотреть файл

@ -1135,7 +1135,7 @@ GetQueryParamFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
RefPtr<nsVariant> result = new nsVariant();
if (!queryString.IsEmpty() && !paramName.IsEmpty()) {
URLParams::Parse(
queryString, true,
queryString,
[&paramName, &result](const nsAString& aName, const nsAString& aValue) {
NS_ConvertUTF16toUTF8 name(aName);
if (!paramName.Equals(name)) {