tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 8725e1596b6b83e1421de5e79bac538b16f40659
parent b0dc617b7c64b3146378a50637c7572d27f34475
Author: hackademix <giorgio@maone.net>
Date:   Wed,  5 Jul 2023 17:05:40 +0200

BB 41854: Allow overriding download spam protection.

Diffstat:
Mbrowser/components/downloads/DownloadSpamProtection.sys.mjs | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mtoolkit/components/downloads/DownloadCore.sys.mjs | 9+++++++--
Mtoolkit/components/downloads/DownloadIntegration.sys.mjs | 5+----
Muriloader/exthandler/nsExternalHelperAppService.cpp | 4+---
4 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/browser/components/downloads/DownloadSpamProtection.sys.mjs b/browser/components/downloads/DownloadSpamProtection.sys.mjs @@ -96,8 +96,9 @@ class WindowSpamProtection { * existing blocked download, then notify listeners about this. * * @param {string} url + * @param {DownloadSpamEnabler} enabler */ - addDownloadSpam(url) { + addDownloadSpam(url, enabler) { this._blocking = true; // Start listening on registered downloads views, if any exist. this._maybeAddViews(); @@ -111,7 +112,7 @@ class WindowSpamProtection { } // Otherwise, create a new DownloadSpam object for the URL, add it to the // spamList, and open the downloads panel. - let downloadSpam = new DownloadSpam(url); + let downloadSpam = new DownloadSpam(url, enabler); this.spamList.add(downloadSpam); this._downloadSpamForUrl.set(url, downloadSpam); this._notifyDownloadSpamAdded(downloadSpam); @@ -199,6 +200,41 @@ class WindowSpamProtection { } /** + * Helper to grant a certain principal permission for automatic downloads + * and to clear its download spam messages from the UI + */ +class DownloadSpamEnabler { + /** + * Constructs a DownloadSpamEnabler object + * + * @param {nsIPrincipal} principal + * @param {DownloadSpamProtection} downloadSpamProtection + */ + constructor(principal, downloadSpamProtection) { + this.principal = principal; + this.downloadSpamProtection = downloadSpamProtection; + } + /** + * Allows a DownloadSpam item + * + * @param {DownloadSpam} downloadSpam + */ + allow(downloadSpam) { + const pm = Services.perms; + pm.addFromPrincipal( + this.principal, + "automatic-download", + pm.ALLOW_ACTION, + pm.EXPIRE_SESSION + ); + downloadSpam.hasBlockedData = downloadSpam.hasPartialData = false; + const { url } = downloadSpam.source; + for (let window of lazy.BrowserWindowTracker.orderedWindows) { + this.downloadSpamProtection.removeDownloadSpamForWindow(url, window); + } + } +} +/** * Responsible for detecting events related to downloads spam and notifying the * relevant window's WindowSpamProtection object. This is a singleton object, * constructed by DownloadIntegration.sys.mjs when the first download is blocked. @@ -217,9 +253,11 @@ export class DownloadSpamProtection { * nsExternalAppHandler::IsDownloadSpam * * @param {string} url - * @param {Window} window + * @param {nsILoadInfo} loadInfo */ - update(url, window) { + update(url, loadInfo) { + loadInfo = loadInfo.QueryInterface(Ci.nsILoadInfo); + const window = loadInfo.browsingContext.topChromeWindow; if (window == null) { lazy.DownloadsCommon.log( "Download spam blocked in a non-chrome window. URL: ", @@ -233,7 +271,10 @@ export class DownloadSpamProtection { let wsp = this._forWindowMap.get(window) ?? new WindowSpamProtection(window); this._forWindowMap.set(window, wsp); - wsp.addDownloadSpam(url); + wsp.addDownloadSpam( + url, + new DownloadSpamEnabler(loadInfo.triggeringPrincipal, this) + ); } /** @@ -297,8 +338,9 @@ export class DownloadSpamProtection { * @augments Download */ class DownloadSpam extends Download { - constructor(url) { + constructor(url, downloadSpamEnabler) { super(); + this._downloadSpamEnabler = downloadSpamEnabler; this.hasBlockedData = true; this.stopped = true; this.error = new DownloadError({ @@ -309,4 +351,13 @@ class DownloadSpam extends Download { this.source = { url }; this.blockedDownloadsCount = 1; } + + /** + * Allows the principal which triggered this download to perform automatic downloads + * and clears the UI from messages reporting this download spam + */ + allow() { + this._downloadSpamEnabler.allow(this); + this._notifyChange(); + } } diff --git a/toolkit/components/downloads/DownloadCore.sys.mjs b/toolkit/components/downloads/DownloadCore.sys.mjs @@ -773,6 +773,10 @@ Download.prototype = { } this._promiseUnblock = (async () => { + if (this.allow) { + this.allow(); + return; + } try { if (this.target.partFilePath) { await IOUtils.move(this.target.partFilePath, this.target.path); @@ -783,7 +787,6 @@ Download.prototype = { this._promiseUnblock = null; throw ex; } - this.succeeded = true; this.hasBlockedData = false; this._notifyChange(); @@ -1058,7 +1061,9 @@ Download.prototype = { await this._promiseCanceled; } // Ask the saver object to remove any partial data. - await this.saver.removeData(); + if (this.saver) { + await this.saver.removeData(); + } // For completeness, clear the number of bytes transferred. if (this.currentBytes != 0 || this.hasPartialData) { this.currentBytes = 0; diff --git a/toolkit/components/downloads/DownloadIntegration.sys.mjs b/toolkit/components/downloads/DownloadIntegration.sys.mjs @@ -1467,10 +1467,7 @@ var DownloadObserver = { case "blocked-automatic-download": if (AppConstants.MOZ_BUILD_APP == "browser") { DownloadIntegration._initializeDownloadSpamProtection(); - DownloadIntegration.downloadSpamProtection.update( - aData, - aSubject.topChromeWindow - ); + DownloadIntegration.downloadSpamProtection.update(aData, aSubject); } break; } diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -1954,13 +1954,11 @@ bool nsExternalAppHandler::IsDownloadSpam(nsIChannel* aChannel) { if (capability == nsIPermissionManager::PROMPT_ACTION) { nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); - RefPtr<BrowsingContext> browsingContext; - loadInfo->GetBrowsingContext(getter_AddRefs(browsingContext)); nsAutoCString cStringURI; loadInfo->TriggeringPrincipal()->GetPrePath(cStringURI); observerService->NotifyObservers( - browsingContext, "blocked-automatic-download", + loadInfo, "blocked-automatic-download", NS_ConvertASCIItoUTF16(cStringURI.get()).get()); // FIXME: In order to escape memory leaks, currently we cancel blocked // downloads. This is temporary solution, because download data should be