3

I have a simple plugin that intercepts new downloads using Downloads.jsm and Task.jsm as suggested in my previous question:

Intercept new downloads in Firefox Addon SDK

The idea is that the add-on should perform the following:

  1. Intercept a download
  2. Cancel the download
  3. Delete any partial data already downloaded
  4. Remove the download from the download history list
  5. Send the download info to an external download manager

Using the following code I am able to intercept a download and get it's information such as source and destination but cancelling and removing the download is causing me a few problems.

const {Cu} = require("chrome");

Cu.import("resource://gre/modules/Downloads.jsm");
Cu.import("resource://gre/modules/Task.jsm");

Task.spawn(function() {
  let list = yield Downloads.getList(Downloads.ALL);

  let view = {
    onDownloadAdded: download => { 
        console.log("Added", download); 

        // cancel the download
        download.cancel(); 

        // finialize (remove partial data)
        download.finalize(true); 

        // delete the partial data
        download.removePartialData();

        // remove it from the list
        list.remove(download); 
    },
    onDownloadChanged: download => console.log("Changed", download),
    onDownloadRemoved: download => console.log("Removed", download)
  };
  yield list.addView(view);
});

The DownloadList and Download objects expose all the functions that I should need but something is not working as expected.

Although the download is removed from the Firefox download list and in the Download Library I can see the download as "Cancelled" the call to finalize(true) does not remove the partial file downloads (neither does removePartialData).

I believe this is because the downloads are not being properly deleted. Even though they are shown as cancelled in the Library if I browse to my downloads folder I can see the .part file growing as if the download was still in progress.

I suspect this might be because I am trying to cancel the download before it really starts so perhaps the download is not processing the cancel() call properly?

Community
  • 1
  • 1
antfx
  • 3,205
  • 3
  • 35
  • 45

1 Answers1

1

Well, those API methods return promises, i.e. it more or less immediately returns and promises to execute the requested action at some time in the future. So you need to wait for the promise to be actually fulfilled (or rejected). Using Task.jsm again:

const {Cu} = require("chrome");

Cu.import("resource://gre/modules/Downloads.jsm");
Cu.import("resource://gre/modules/Task.jsm");

let view = {
  onDownloadAdded: download => { 
    Task.spawn(function() {
      try {
        console.log("Added", download); 

        // cancel the download
        yield download.cancel(); 

        // delete the partial data
        yield download.removePartialData();

        // remove it from the list
        yield list.remove(download); 

      } catch (ex) {
        console.error(ex);
      }
    });
  },
  onDownloadChanged: download => console.log("Changed", download),
  onDownloadRemoved: download => console.log("Removed", download)
};
Task.spawn(function() {
  let list = yield Downloads.getList(Downloads.ALL);

  yield list.addView(view);
});
nmaier
  • 32,336
  • 5
  • 63
  • 78
  • This still seems to have the problem.. the download shows as cancelled in the list but it actually continues downloading if you look in the download folder? The difference with your code is it now showing an error when trying to delete the partial data " Message: Win error 32 during operation remove on file C:\Users\miked_000\Downloads\1GB(3).zip.part (The process cannot access the file because it is being used by another process.) – antfx Jun 28 '14 at 14:44
  • 1
    Ah, Windows file locking :p Maybe some Anti-Virus tool hogging the Downloaded file. Probably a good idea to remove that `.finalize()` call anyway... Meant to remove it, but forgot :p I might try that out later on a Windows box (worked on OSX). – nmaier Jun 28 '14 at 14:52
  • It's not just that, the file is actually still downloading.. pressing refresh in windows I can see the file size increasing even though the file is supposed to have been cancelled. – antfx Jun 28 '14 at 14:55
  • Hmm. Interesting. Might be `OS.File` still writing buffered data or something. – nmaier Jun 28 '14 at 14:56
  • What happens if you `yield download.start()` before `.cancel()`? – nmaier Jun 28 '14 at 14:59
  • I don't think it is just a buffering thing, looking a the performance tab in Task Manager I can see FF downloading at 3mb/s even though the download has been cancelled and the file continues to grow until I close the app (up to 200mb). Calling start before cancel stops cancel from working – antfx Jun 28 '14 at 15:09
  • 3
    it has something to do with the cancel being called from within the onDownloadAdded event I think. If I cancel the download from within the onDownloadChanged event, it cancels as expected. Perhaps a bug in FF for Windows? – antfx Jun 28 '14 at 16:13
  • Maybe in `onDownlaodAdded` callback, instead of a `.cancel` there is like a `.abort` did you try `console.log`ing the arguments that come into it? Be sure to look under the `prototype` of it, it might have some useful functions. – Blagoh Jul 05 '14 at 05:04