richard pushed to branch base-browser-115.0esrbase-13.0-1 at The Tor Project / Applications / Tor Browser
Commits: 84e468a9 by hackademix at 2023-07-11T22:19:11+00:00 Bug 41854: Allow overriding download spam protection.
- - - - -
4 changed files:
- browser/components/downloads/DownloadSpamProtection.sys.mjs - toolkit/components/downloads/DownloadCore.sys.mjs - toolkit/components/downloads/DownloadIntegration.sys.mjs - uriloader/exthandler/nsExternalHelperAppService.cpp
Changes:
===================================== browser/components/downloads/DownloadSpamProtection.sys.mjs ===================================== @@ -94,8 +94,9 @@ class WindowSpamProtection { * Add a blocked download to the spamList or increment the count of an * 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(); @@ -109,7 +110,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); @@ -193,6 +194,39 @@ 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, @@ -210,9 +244,11 @@ export class DownloadSpamProtection { * download was blocked. This is invoked when a download is blocked by * 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: ", @@ -226,7 +262,7 @@ 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)); }
/** @@ -285,8 +321,9 @@ export class DownloadSpamProtection { * @extends Download */ class DownloadSpam extends Download { - constructor(url) { + constructor(url, downloadSpamEnabler) { super(); + this._downloadSpamEnabler = downloadSpamEnabler; this.hasBlockedData = true; this.stopped = true; this.error = new DownloadError({ @@ -297,4 +334,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(); + } }
===================================== toolkit/components/downloads/DownloadCore.sys.mjs ===================================== @@ -713,6 +713,10 @@ Download.prototype = { }
this._promiseUnblock = (async () => { + if (this.allow) { + this.allow(); + return; + } try { await IOUtils.move(this.target.partFilePath, this.target.path); await this.target.refresh(); @@ -721,7 +725,6 @@ Download.prototype = { this._promiseUnblock = null; throw ex; } - this.succeeded = true; this.hasBlockedData = false; this._notifyChange(); @@ -951,7 +954,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;
===================================== toolkit/components/downloads/DownloadIntegration.sys.mjs ===================================== @@ -1162,7 +1162,7 @@ var DownloadObserver = { DownloadIntegration._initializeDownloadSpamProtection(); DownloadIntegration.downloadSpamProtection.update( aData, - aSubject.topChromeWindow + aSubject ); } break;
===================================== uriloader/exthandler/nsExternalHelperAppService.cpp ===================================== @@ -1907,13 +1907,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
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/84e468a9...