[Conkeror] [Patch v2] save_uri: optionally use a temporary download file

David Kettler kettler at internode.on.net
Thu Feb 12 02:47:37 PST 2009


This is useful when it is undesirable for some other tool to attempt
to open the downloaded file before it is complete.

If $temp_file is specified then the uri is downloaded to that file and
then renamed to the output_file when the download is finished.  If
$temp_file is the value true then a new temporary file in the same
directory as output_file is used.

The download manager indicates this by showing the output_file name
parenthetically.

Note that this save_uri usage of the term "temporary" is different to
the download-manager usage; in that case the file is deleted, not
renamed.
---

This version uses download_finished_hook.  I'm not sure that's worked
out well; I preferred the former version.  I attach a hook for each
download, then remove it again in the hook function; that's a bit
yucky.  Maybe it would be better to have a single hook function, but
also to attach a finished_function to the info object.  The hook could
call that function, if it's defined.  That wouldn't require changes to
download-manager for defining or calling finished_function.

This version also fixes download-delete-target so that it will still
function properly.  It does this by changing target_file to reflect
the rename.  To do this it was necessary to separate target_file from
the service property targetFile, because the latter is immutable.
---
 modules/download-manager.js |   21 ++++++++++++++++-----
 modules/save.js             |   21 ++++++++++++++++++---
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/modules/download-manager.js b/modules/download-manager.js
index 888ef6a..65724e3 100644
--- a/modules/download-manager.js
+++ b/modules/download-manager.js
@@ -169,13 +169,18 @@ const DOWNLOAD_NOT_TEMPORARY = 0;
 const DOWNLOAD_TEMPORARY_FOR_ACTION = 1;
 const DOWNLOAD_TEMPORARY_FOR_COMMAND = 2;
 
-function download_info(source_buffer, mozilla_info) {
+function download_info(source_buffer, mozilla_info, target_file) {
     this.source_buffer = source_buffer;
+    this.target_file = target_file;
     if (mozilla_info != null)
         this.attach(mozilla_info);
 }
 download_info.prototype = {
     attach : function (mozilla_info) {
+        if (!this.target_file)
+            target_file = this.mozilla_info.targetFile;
+        else if (this.target_file.path != mozilla_info.targetFile.path)
+            throw interactive_error("Download target file unexpected.");
         this.mozilla_info = mozilla_info;
         id_to_download_info[mozilla_info.id] = this;
         download_added_hook.run(this);
@@ -202,7 +207,7 @@ download_info.prototype = {
 
     // Reflectors to properties of nsIDownload
     get state () { return this.mozilla_info.state; },
-    get target_file () { return this.mozilla_info.targetFile; },
+    get display_name () { return this.mozilla_info.displayName; },
     get amount_transferred () { return this.mozilla_info.amountTransferred; },
     get percent_complete () { return this.mozilla_info.percentComplete; },
     get size () {
@@ -357,8 +362,8 @@ download_info.prototype = {
 var define_download_local_hook = simple_local_hook_definer();
 
 // FIXME: add more parameters
-function register_download(buffer, source_uri) {
-    var info = new download_info(buffer);
+function register_download(buffer, source_uri, target_file) {
+    var info = new download_info(buffer, null, target_file);
     info.registered_time_stamp = Date.now();
     info.registered_source_uri = source_uri;
     unmanaged_download_info_list.push(info);
@@ -719,7 +724,13 @@ download_buffer.prototype = {
             target_label = "Target:";
         g.text(target_label, label);
         value = g.element("div", div, "class", "download-value");
-        g.text(info.target_file.path, value);
+        {
+            let target = info.target_file.path;
+            let display = info.display_name;
+            if (target.indexOf(display, target.length - display.length) == -1)
+                target = target + " (" + display + ")";
+            g.text(target, value);
+        }
 
         div = g.element("div", d.body, "class", "download-info", "id", "download-mime-type");
         label = g.element("div", div, "class", "download-label");
diff --git a/modules/save.js b/modules/save.js
index 23e7115..0a7e3ea 100644
--- a/modules/save.js
+++ b/modules/save.js
@@ -12,7 +12,7 @@ require("load-spec.js");
 require("suggest-file-name.js");
 
 /* buffer is used only to associate with the download */
-define_keywords("$use_cache", "$buffer", "$prepare_download");
+define_keywords("$use_cache", "$buffer", "$prepare_download", "$temp_file");
 function save_uri(lspec, output_file) {
     keywords(arguments, $use_cache = true);
 
@@ -22,6 +22,15 @@ function save_uri(lspec, output_file) {
 
     var prepare_download = arguments.$prepare_download;
 
+    let temp_file = arguments.$temp_file;
+    if (temp_file == true) {
+        temp_file = Cc["@mozilla.org/file/local;1"]
+            .createInstance(Ci.nsILocalFile);
+        temp_file.initWithFile(output_file);
+        temp_file.leafName = "temp";
+        temp_file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+    }
+
     var cache_key = null;
     var uri = load_spec_uri(lspec);
     var referrer_uri = load_spec_referrer(lspec);
@@ -29,7 +38,7 @@ function save_uri(lspec, output_file) {
     if (use_cache)
         cache_key = load_spec_cache_key(lspec);
 
-    var file_uri = make_uri(output_file);
+    var file_uri = make_uri(temp_file || output_file);
 
     var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
         .createInstance(Ci.nsIWebBrowserPersist);
@@ -44,7 +53,13 @@ function save_uri(lspec, output_file) {
     else
         persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_BYPASS_CACHE;
 
-    var info = register_download(buffer, uri);
+    var info = register_download(buffer, uri, temp_file || output_file);
+    if (temp_file)
+        add_hook("download_finished_hook", function(info) {
+            remove_hook("download_finished_hook", arguments.callee);
+            temp_file.moveTo(null, output_file.leafName);
+            info.target_file.leafName = output_file.leafName;
+        });
     if (prepare_download)
         prepare_download(info);
 
-- 
1.5.6.5



More information about the Conkeror mailing list