Loading browser/components/downloads/DownloadSpamProtection.sys.mjs +55 −6 Original line number Diff line number Diff line Loading @@ -89,8 +89,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(); Loading @@ -104,7 +105,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); Loading Loading @@ -188,6 +189,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, Loading @@ -205,9 +239,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: ", Loading @@ -221,7 +257,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) ); } /** Loading Loading @@ -280,8 +319,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({ Loading @@ -292,4 +332,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 +7 −2 Original line number Diff line number Diff line Loading @@ -722,6 +722,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); Loading @@ -732,7 +736,6 @@ Download.prototype = { this._promiseUnblock = null; throw ex; } this.succeeded = true; this.hasBlockedData = false; this._notifyChange(); Loading Loading @@ -1003,7 +1006,9 @@ Download.prototype = { await this._promiseCanceled; } // Ask the saver object to remove any partial data. if (this.saver) { await this.saver.removeData(); } // For completeness, clear the number of bytes transferred. if (this.currentBytes != 0 || this.hasPartialData) { this.currentBytes = 0; Loading toolkit/components/downloads/DownloadIntegration.sys.mjs +1 −4 Original line number Diff line number Diff line Loading @@ -1387,10 +1387,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; } Loading uriloader/exthandler/nsExternalHelperAppService.cpp +1 −3 Original line number Diff line number Diff line Loading @@ -1942,13 +1942,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 Loading Loading
browser/components/downloads/DownloadSpamProtection.sys.mjs +55 −6 Original line number Diff line number Diff line Loading @@ -89,8 +89,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(); Loading @@ -104,7 +105,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); Loading Loading @@ -188,6 +189,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, Loading @@ -205,9 +239,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: ", Loading @@ -221,7 +257,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) ); } /** Loading Loading @@ -280,8 +319,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({ Loading @@ -292,4 +332,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 +7 −2 Original line number Diff line number Diff line Loading @@ -722,6 +722,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); Loading @@ -732,7 +736,6 @@ Download.prototype = { this._promiseUnblock = null; throw ex; } this.succeeded = true; this.hasBlockedData = false; this._notifyChange(); Loading Loading @@ -1003,7 +1006,9 @@ Download.prototype = { await this._promiseCanceled; } // Ask the saver object to remove any partial data. if (this.saver) { await this.saver.removeData(); } // For completeness, clear the number of bytes transferred. if (this.currentBytes != 0 || this.hasPartialData) { this.currentBytes = 0; Loading
toolkit/components/downloads/DownloadIntegration.sys.mjs +1 −4 Original line number Diff line number Diff line Loading @@ -1387,10 +1387,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; } Loading
uriloader/exthandler/nsExternalHelperAppService.cpp +1 −3 Original line number Diff line number Diff line Loading @@ -1942,13 +1942,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 Loading