Backed out changeset a9a15832f816 (bug 1725354) for bc failures on browser_download_privatebrowsing.js

This commit is contained in:
Narcis Beleuzu 2021-11-05 23:22:42 +02:00
parent a23f838d22
commit 497da78210
14 changed files with 11 additions and 392 deletions

View File

@ -1,106 +0,0 @@
/* 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/. */
/**
* Provides functions to prevent multiple automatic downloads.
*/
"use strict";
var EXPORTED_SYMBOLS = ["DownloadSpamProtection"];
const { Download, DownloadError } = ChromeUtils.import(
"resource://gre/modules/DownloadCore.jsm"
);
var { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyModuleGetters(this, {
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
Downloads: "resource://gre/modules/Downloads.jsm",
DownloadsCommon: "resource:///modules/DownloadsCommon.jsm",
DownloadList: "resource://gre/modules/DownloadList.jsm",
});
/**
* Responsible for detecting events related to downloads spam and updating the
* downloads UI with this information.
*/
class DownloadSpamProtection {
static TOPIC = "blocked-automatic-download";
constructor() {
/**
* Tracks URLs we have detected download spam for.
* @type {Map<string, DownloadSpam>}
*/
this._blockedURLToDownloadSpam = new Map();
this._browserWin = BrowserWindowTracker.getTopWindow();
this._indicator = DownloadsCommon.getIndicatorData(this._browserWin);
this.list = new DownloadList();
}
get spamList() {
return this.list;
}
async observe(aSubject, aTopic, URL) {
if (aTopic != DownloadSpamProtection.TOPIC) {
return;
}
if (this._blockedURLToDownloadSpam.has(URL)) {
let downloadSpam = this._blockedURLToDownloadSpam.get(URL);
this.spamList.remove(downloadSpam);
downloadSpam.blockedDownloadsCount += 1;
this.spamList.add(downloadSpam);
this._indicator.onDownloadStateChanged(downloadSpam);
return;
}
let downloadSpam = new DownloadSpam(URL);
this.spamList.add(downloadSpam);
this._blockedURLToDownloadSpam.set(URL, downloadSpam);
let hasActiveDownloads = DownloadsCommon.summarizeDownloads(
this._indicator._activeDownloads()
).numDownloading;
if (!hasActiveDownloads) {
this._browserWin.DownloadsPanel.showPanel();
}
this._indicator.onDownloadAdded(downloadSpam);
}
/**
* Removes the download spam data for the current url.
*/
clearDownloadSpam(URL) {
if (this._blockedURLToDownloadSpam.has(URL)) {
let downloadSpam = this._blockedURLToDownloadSpam.get(URL);
this.spamList.remove(downloadSpam);
this._indicator.onDownloadRemoved(downloadSpam);
this._blockedURLToDownloadSpam.delete(URL);
}
}
}
/**
* Represents a special Download object for download spam.
* @extends Download
*/
class DownloadSpam extends Download {
constructor(url) {
super();
this.hasBlockedData = true;
this.stopped = true;
this.error = new DownloadError({
becauseBlockedByReputationCheck: true,
reputationCheckVerdict: Downloads.Error.BLOCK_VERDICT_DOWNLOAD_SPAM,
});
this.target = { path: "" };
this.source = { url };
this.blockedDownloadsCount = 1;
}
}

View File

@ -1265,7 +1265,6 @@ DownloadsIndicatorDataCtor.prototype = {
break;
case Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED: // fall-through
case Downloads.Error.BLOCK_VERDICT_INSECURE:
case Downloads.Error.BLOCK_VERDICT_DOWNLOAD_SPAM:
// Existing higher level attention indication trumps ATTENTION_WARNING.
if (this._attention != DownloadsCommon.ATTENTION_SEVERE) {
this.attention = DownloadsCommon.ATTENTION_WARNING;

View File

@ -24,7 +24,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
DownloadsCommon: "resource:///modules/DownloadsCommon.jsm",
FileUtils: "resource://gre/modules/FileUtils.jsm",
OS: "resource://gre/modules/osfile.jsm",
UrlbarUtils: "resource:///modules/UrlbarUtils.jsm",
});
XPCOMUtils.defineLazyServiceGetter(
@ -120,16 +119,6 @@ var DownloadsViewUI = {
return name.startsWith("cmd_") || name.startsWith("downloadsCmd_");
},
/**
* Get source url of the download without'http' or'https' prefix.
*/
getStrippedUrl(download) {
return UrlbarUtils.stripPrefixAndTrim(download?.source?.url, {
stripHttp: true,
stripHttps: true,
})[0];
},
/**
* Returns the user-facing label for the given Download object. This is
* normally the leaf name of the download target file. In case this is a very
@ -137,16 +126,6 @@ var DownloadsViewUI = {
* source URI is displayed.
*/
getDisplayName(download) {
if (
download.error?.reputationCheckVerdict ==
Downloads.Error.BLOCK_VERDICT_DOWNLOAD_SPAM
) {
let l10n = {
id: "downloads-blocked-from-url",
args: { url: DownloadsViewUI.getStrippedUrl(download) },
};
return { l10n };
}
return download.target.path
? OS.Path.basename(download.target.path)
: download.source.url;
@ -430,17 +409,8 @@ DownloadsViewUI.DownloadElementShell.prototype = {
* URL of the icon to load, generally from the "image" property.
*/
showDisplayNameAndIcon(displayName, icon) {
if (displayName.l10n) {
let document = this.element.ownerDocument;
document.l10n.setAttributes(
this._downloadTarget,
displayName.l10n.id,
displayName.l10n.args
);
} else {
this._downloadTarget.setAttribute("value", displayName);
this._downloadTarget.setAttribute("tooltiptext", displayName);
}
this._downloadTarget.setAttribute("value", displayName);
this._downloadTarget.setAttribute("tooltiptext", displayName);
this._downloadTypeIcon.setAttribute("src", icon);
},
@ -520,10 +490,6 @@ DownloadsViewUI.DownloadElementShell.prototype = {
* Downloads View. Type is either l10n object or string literal.
*/
showStatusWithDetails(stateLabel, hoverStatus) {
if (stateLabel.l10n) {
this.showStatus(stateLabel, hoverStatus);
return;
}
let [displayHost] = DownloadUtils.getURIHost(this.download.source.url);
let [displayDate] = DownloadUtils.getReadableDates(
new Date(this.download.endTime)
@ -735,9 +701,6 @@ DownloadsViewUI.DownloadElementShell.prototype = {
this.showButton("askRemoveFileOrAllow");
}
break;
case Downloads.Error.BLOCK_VERDICT_DOWNLOAD_SPAM:
this.showButton("askRemoveFileOrAllow");
break;
default:
// Assume Downloads.Error.BLOCK_VERDICT_MALWARE
this.showButton("removeFile");
@ -810,7 +773,6 @@ DownloadsViewUI.DownloadElementShell.prototype = {
/**
* Returns [title, [details1, details2]] for blocked downloads.
* The title or details could be raw strings or l10n objects.
*/
get rawBlockedTitleAndDetails() {
let s = DownloadsCommon.strings;
@ -835,19 +797,6 @@ DownloadsViewUI.DownloadElementShell.prototype = {
];
case Downloads.Error.BLOCK_VERDICT_MALWARE:
return [s.blockedMalware, [s.unblockTypeMalware, s.unblockTip2]];
case Downloads.Error.BLOCK_VERDICT_DOWNLOAD_SPAM:
let title = {
id: "downloads-files-not-downloaded",
args: {
num: this.download.blockedDownloadsCount,
},
};
let details = {
id: "downloads-blocked-download-detailed-info",
args: { url: DownloadsViewUI.getStrippedUrl(this.download) },
};
return [{ l10n: title }, [{ l10n: details }, null]];
}
throw new Error(
"Unexpected reputationCheckVerdict: " +

View File

@ -89,17 +89,6 @@ ChromeUtils.defineModuleGetter(
"resource://gre/modules/PlacesUtils.jsm"
);
const { Integration } = ChromeUtils.import(
"resource://gre/modules/Integration.jsm"
);
/* global DownloadIntegration */
Integration.downloads.defineModuleGetter(
this,
"DownloadIntegration",
"resource://gre/modules/DownloadIntegration.jsm"
);
// DownloadsPanel
/**
@ -161,11 +150,6 @@ var DownloadsPanel = {
DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit).addView(
DownloadsSummary
);
DownloadIntegration.getDownloadSpamProtection().spamList.addView(
DownloadsView
);
DownloadsCommon.log(
"DownloadsView attached - the panel for this window",
"should now see download items come in."
@ -1576,19 +1560,8 @@ var DownloadsBlockedSubview = {
let e = this.elements;
let s = DownloadsCommon.strings;
title.l10n
? document.l10n.setAttributes(e.title, title.l10n.id, title.l10n.args)
: (e.title.textContent = title);
details[0].l10n
? document.l10n.setAttributes(
e.details1,
details[0].l10n.id,
details[0].l10n.args
)
: (e.details1.textContent = details[0]);
e.title.textContent = title;
e.details1.textContent = details[0];
e.details2.textContent = details[1];
if (download.launchWhenSucceeded) {

View File

@ -13,7 +13,6 @@ JAR_MANIFESTS += ["jar.mn"]
EXTRA_JS_MODULES += [
"DownloadsCommon.jsm",
"DownloadSpamProtection.jsm",
"DownloadsTaskbar.jsm",
"DownloadsViewableInternally.jsm",
"DownloadsViewUI.jsm",

View File

@ -27,8 +27,6 @@ skip-if = os == "linux" # Bug 952422
skip-if = (os == 'win' && os_version == '10.0' && ccov) # Bug 1306510
[browser_library_clearall.js]
[browser_download_opens_on_click.js]
[browser_download_spam_protection.js]
support-files = test_spammy_page.html
[browser_download_is_clickable.js]
[browser_downloads_panel_block.js]
skip-if = true # Bug 1352792

View File

@ -1,131 +0,0 @@
/* 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/. */
"use strict";
var { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"DownloadSpamProtection",
"resource:///modules/DownloadSpamProtection.jsm"
);
XPCOMUtils.defineLazyModuleGetters(this, {
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
PermissionTestUtils: "resource://testing-common/PermissionTestUtils.jsm",
});
const TEST_URI = "https://example.com";
const TEST_PATH = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
TEST_URI
);
add_task(async function setup() {
PermissionTestUtils.add(
TEST_URI,
"automatic-download",
Services.perms.UNKNOWN
);
await SpecialPowers.pushPrefEnv({
set: [
["browser.download.improvements_to_download_panel", true], // To avoid the saving dialog being shown
["browser.download.enable_spam_prevention", true],
],
});
});
add_task(async function check_download_spam_ui() {
let spamProtection = DownloadIntegration.getDownloadSpamProtection();
let oldFunction = spamProtection.observe.bind(spamProtection);
let blockedDownloads = PromiseUtils.defer();
let counter = 0;
let newFunction = async (aSubject, aTopic, URL) => {
await oldFunction(aSubject, aTopic, URL);
counter++;
if (counter == 99) {
blockedDownloads.resolve();
}
};
spamProtection.observe = newFunction;
let newTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_PATH + "test_spammy_page.html"
);
registerCleanupFunction(async () => {
spamProtection.observe = oldFunction;
BrowserWindowTracker.getTopWindow().DownloadsPanel.hidePanel();
DownloadIntegration.getDownloadSpamProtection().clearDownloadSpam(TEST_URI);
let publicList = await Downloads.getList(Downloads.PUBLIC);
let downloads = await publicList.getAll();
for (let download of downloads) {
await publicList.remove(download);
try {
info("removing " + download.target.path);
if (Services.appinfo.OS === "WINNT") {
// We need to make the file writable to delete it on Windows.
await IOUtils.setPermissions(download.target.path, 0o600);
}
await IOUtils.remove(download.target.path);
} catch (ex) {
info("The file " + download.target.path + " is not removed, " + ex);
}
}
BrowserTestUtils.removeTab(newTab);
});
await BrowserTestUtils.synthesizeMouseAtCenter(
"body",
{},
newTab.linkedBrowser
);
await blockedDownloads.promise;
let spamList = spamProtection.spamList;
is(
spamList._downloads[0].blockedDownloadsCount,
99,
"99 blocked downloads recorded"
);
ok(
spamList._downloads[0].error.becauseBlockedByReputationCheck,
"Download blocked because of reputation"
);
is(
spamList._downloads[0].error.reputationCheckVerdict,
"DownloadSpam",
"Verdict is DownloadSpam"
);
let browserWin = BrowserWindowTracker.getTopWindow();
await BrowserTestUtils.waitForPopupEvent(
browserWin.DownloadsPanel.panel,
"shown"
);
ok(browserWin.DownloadsPanel.isPanelShowing, "Download panel should open");
let listbox = document.getElementById("downloadsListBox");
ok(listbox, "Download list box present");
await TestUtils.waitForCondition(() => {
return listbox.childElementCount == 2;
}, "2 downloads = 1 allowed download and 1 for 99 downloads blocked");
let spamElement = listbox.itemChildren[0].classList.contains(
"temporary-block"
)
? listbox.itemChildren[0]
: listbox.itemChildren[1];
ok(spamElement.classList.contains("temporary-block"), "Download is blocked");
});

View File

@ -1,26 +0,0 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Spam Page Test</title>
</head>
<body>
<p> Hello, it's the spammy page! </p>
<script type="text/javascript">
let count = 0;
window.onload = window.onclick = function() {
if (count < 100) {
count++;
let l = document.createElement('a');
l.href = 'data:text/plain,some text';
l.download = 'sometext.txt';
document.body.appendChild(l);
l.click();
}
}
</script>
</body>
</html>

View File

@ -169,20 +169,6 @@ downloads-history =
downloads-details =
.title = Download Details
## Displayed when a site attempts to automatically download many files.
## Variables:
## $num (number) - Number of blocked downloads.
## $url (string) - The url of the suspicious site, stripped of http, https and www prefix.
downloads-files-not-downloaded = { $num ->
[one] File not downloaded.
*[other] {$num} files not downloaded.
}
downloads-blocked-from-url = Downloads blocked from { $url }.
downloads-blocked-download-detailed-info = { $url } attempted to automatically download multiple files. The site could be broken or trying to store spam files on your device.
##
downloads-clear-downloads-button =
.label = Clear Downloads
.tooltiptext = Clears completed, canceled and failed downloads

View File

@ -53,9 +53,7 @@
}
#downloadsPanel-blockedSubview[verdict="PotentiallyUnwanted"] .downloadsPanel-blockedSubview-image,
#downloadsPanel-blockedSubview[verdict="DownloadSpam"] .downloadsPanel-blockedSubview-image,
@item@[verdict="PotentiallyUnwanted"] .downloadBlockedBadge,
@item@[verdict="DownloadSpam"] .downloadBlockedBadge {
@item@[verdict="PotentiallyUnwanted"] .downloadBlockedBadge {
-moz-context-properties: fill;
fill: #ffbf00;
background-image: url("chrome://global/skin/icons/warning.svg");

View File

@ -45,7 +45,6 @@
@item@:is(.openWhenFinished).hoveringMainArea:hover,
@item@:not([verdict]) > .downloadButton:hover,
@item@[verdict]:hover,
@item@:hover:is(.openWhenFinished),
.downloadsPanelFooterButton:hover {
background-color: var(--panel-item-hover-bgcolor);
}

View File

@ -1829,7 +1829,6 @@ DownloadError.BLOCK_VERDICT_MALWARE = "Malware";
DownloadError.BLOCK_VERDICT_POTENTIALLY_UNWANTED = "PotentiallyUnwanted";
DownloadError.BLOCK_VERDICT_INSECURE = "Insecure";
DownloadError.BLOCK_VERDICT_UNCOMMON = "Uncommon";
DownloadError.BLOCK_VERDICT_DOWNLOAD_SPAM = "DownloadSpam";
DownloadError.prototype = {
__proto__: Error.prototype,

View File

@ -113,12 +113,6 @@ XPCOMUtils.defineLazyGetter(this, "gParentalControlsService", function() {
return null;
});
ChromeUtils.defineModuleGetter(
this,
"DownloadSpamProtection",
"resource:///modules/DownloadSpamProtection.jsm"
);
XPCOMUtils.defineLazyServiceGetter(
this,
"gApplicationReputationService",
@ -963,16 +957,6 @@ var DownloadIntegration = {
_getDirectory(name) {
return Services.dirsvc.get(name, Ci.nsIFile).path;
},
/**
* Returns the DownloadSpamProtection instance.
* This is used to observe and group multiple automatic downloads.
*/
getDownloadSpamProtection() {
if (!this._downloadSpamProtection) {
this._downloadSpamProtection = new DownloadSpamProtection();
}
return this._downloadSpamProtection;
},
/**
* Register the downloads interruption observers.
@ -992,12 +976,6 @@ var DownloadIntegration = {
for (let topic of kObserverTopics) {
Services.obs.addObserver(DownloadObserver, topic);
}
if (AppConstants.MOZ_BUILD_APP == "browser") {
Services.obs.addObserver(
this.getDownloadSpamProtection(),
DownloadSpamProtection.TOPIC
);
}
}
return Promise.resolve();
},

View File

@ -2010,6 +2010,11 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) {
bool nsExternalAppHandler::IsDownloadSpam(nsIChannel* aChannel) {
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
if (loadInfo->GetHasValidUserGestureActivation()) {
return false;
}
nsCOMPtr<nsIPermissionManager> permissionManager =
mozilla::services::GetPermissionManager();
nsCOMPtr<nsIPrincipal> principal = loadInfo->TriggeringPrincipal();
@ -2050,8 +2055,7 @@ bool nsExternalAppHandler::IsDownloadSpam(nsIChannel* aChannel) {
// End cancel
return true;
}
}
if (!loadInfo->GetHasValidUserGestureActivation()) {
} else {
permissionManager->AddFromPrincipal(
principal, type, nsIPermissionManager::PROMPT_ACTION,
nsIPermissionManager::EXPIRE_NEVER, 0 /* expire time */);