From 485930a7bc3b380693f9afeb7cabf144f16fa8cf Mon Sep 17 00:00:00 2001 From: Eli Grey Date: Mon, 21 Jul 2014 13:48:56 -0400 Subject: [PATCH] Workaround for crbug.com/375297 Removed deletion queue + unload processing; replaced it with an asynchronous revocation flow --- FileSaver.js | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/FileSaver.js b/FileSaver.js index 6e1fc3c..e7c05d5 100644 --- a/FileSaver.js +++ b/FileSaver.js @@ -1,6 +1,6 @@ /* FileSaver.js * A saveAs() FileSaver implementation. - * 2014-05-27 + * 2014-07-21 * * By Eli Grey, http://eligrey.com * License: X11/MIT @@ -49,18 +49,17 @@ var saveAs = saveAs } , force_saveable_type = "application/octet-stream" , fs_min_size = 0 - , deletion_queue = [] - , process_deletion_queue = function() { - var i = deletion_queue.length; - while (i--) { - var file = deletion_queue[i]; + // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 for + // the reasoning behind the timeout and revocation flow + , arbitrary_revoke_timeout = 10 + , revoke = function(file) { + setTimeout(function() { if (typeof file === "string") { // file is an object URL get_URL().revokeObjectURL(file); } else { // file is a File file.remove(); } - } - deletion_queue.length = 0; // clear queue + }, arbitrary_revoke_timeout); } , dispatch = function(filesaver, event_types, event) { event_types = [].concat(event_types); @@ -84,11 +83,6 @@ var saveAs = saveAs , blob_changed = false , object_url , target_view - , get_object_url = function() { - var object_url = get_URL().createObjectURL(blob); - deletion_queue.push(object_url); - return object_url; - } , dispatch_all = function() { dispatch(filesaver, "writestart progress write writeend".split(" ")); } @@ -96,15 +90,16 @@ var saveAs = saveAs , fs_error = function() { // don't create more object URLs than needed if (blob_changed || !object_url) { - object_url = get_object_url(blob); + object_url = get_URL().createObjectURL(blob); } if (target_view) { target_view.location.href = object_url; } else { - window.open(object_url, "_blank"); + view.open(object_url, "_blank"); } filesaver.readyState = filesaver.DONE; dispatch_all(); + revoke(object_url); } , abortable = function(func) { return function() { @@ -121,17 +116,20 @@ var saveAs = saveAs name = "download"; } if (can_use_save_link) { - object_url = get_object_url(blob); + object_url = get_URL().createObjectURL(blob); save_link.href = object_url; save_link.download = name; click(save_link); filesaver.readyState = filesaver.DONE; dispatch_all(); + revoke(object_url); return; } // Object and web filesystem URLs have a problem saving in Google Chrome when // viewed in a tab, so I force save with application/octet-stream // http://code.google.com/p/chromium/issues/detail?id=91158 + // Update: Google errantly closed 91158, I submitted it again: + // https://code.google.com/p/chromium/issues/detail?id=389642 if (view.chrome && type && type !== force_saveable_type) { slice = blob.slice || blob.webkitSlice; blob = slice.call(blob, 0, blob.size, force_saveable_type); @@ -158,9 +156,9 @@ var saveAs = saveAs file.createWriter(abortable(function(writer) { writer.onwriteend = function(event) { target_view.location.href = file.toURL(); - deletion_queue.push(file); filesaver.readyState = filesaver.DONE; dispatch(filesaver, "writeend", event); + revoke(file); }; writer.onerror = function() { var error = writer.error; @@ -217,11 +215,6 @@ var saveAs = saveAs FS_proto.onwriteend = null; - view.addEventListener("unload", process_deletion_queue, false); - saveAs.unload = function() { - process_deletion_queue(); - view.removeEventListener("unload", process_deletion_queue, false); - }; return saveAs; }( typeof self !== "undefined" && self