I have written a simple download manager for Windows and I would like to create an addon for Firefox that when enabled intercepts new downloads in Firefox and sends them to the download manager.
I have already done this for Google Chrome using:
chrome.downloads.onCreated.addListener(function(details) {
// stop the download
chrome.downloads.cancel(details.id, null);
}
The question is how can I achieve something similar using the Firefox add-on SDK.
I see there is a way of intercepting page loads to view the content / headers which might be helpful but then I won't know if the request will turn into a download or not.
Firefox add-on SDK: Get http response headers
I could perhaps look for a content type that is not text/html or check for a content disposition header but that could cause problems if I don't correctly handle all cases.
Is there no way of accessing the download manager using the JS SDK or some way of knowing when a download has been started / being started and stop it?
The http-on-examine-response
observer that the linked question discusses is the wrong way to go. It concerns all requests not just downloads.
Instead use the Downloads.jsm
to observe new downloads, then cancel them, and so on.
To load Downloads.jsm
in the SDK use:
const {Cu} = require("chrome");
Cu.import("resource://gre/modules/Downloads.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Then you can add your listener.
let view = {
onDownloadAdded: function(download) {
console.log("Added", download);
},
onDownloadChanged: function(download) {
console.log("Changed", download);
},
onDownloadRemoved: function(download) {
console.log("Removed", download);
}
};
Task.spawn(function() {
try {
let list = yield Downloads.getList(Downloads.ALL);
yield list.addView(view);
} catch (ex) {
console.error(ex);
}
});
The linked MDN docs have more information and samples.
Since your add-on is a restartless SDK add-on, you'll need to remove the listener again using .removeView
on unload, or else there will be a memory leak.
Here's the JSM way.
Components.utils.import("resource://gre/modules/Downloads.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
var view = {
onDownloadChanged: function (download) {
console.log(download, 'Changed');
if (download.succeeded) {
var file = new FileUtils.File(this.target.path);
console.log('file', file);
}
}
};
var list;
Task.spawn(function () {
list = yield Downloads.getList(Downloads.ALL);
list.addView(view);
}).then(null, Components.utils.reportError);
Remember to removeView
to stop listening. Can do this anywhere, like in shutdown
function or whatever, doesn't have to be within that Task.spawn
so list
must be global var.
list.removeView(view); //to stop listening
Here's the old way, which seems to still work. Although I thought they said they're going to take out the old downloadManager:
var observerService = Components.classes["@mozilla.org/download-manager;1"].getService(Components.interfaces.nsIDownloadManager);
observerService.addListener({
onDownloadStateChange: function (state, dl) {
console.log('dl=', dl);
console.log('state=', state);
console.log('targetFile', dl.targetFile);
if (state == 7 && dl.targetFile.leafName.substr(-4) == ".txt") {
//guys just downloaded (succesfully) a .txt file
}
}
});
Heres a mozillazine with some more on this: http://forums.mozillazine.org/viewtopic.php?f=19&t=2792021
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With