From 92886e639d1aebdd3b3305e99d757ccf335281db Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 4 Nov 2016 20:50:37 -0700 Subject: [PATCH] GUACAMOLE-105: Clean up download iframe only after download has truly completed. If completion cannot be determined, wait a reasonable amount of time before assuming completion. --- .../webapp/app/rest/services/tunnelService.js | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/guacamole/src/main/webapp/app/rest/services/tunnelService.js b/guacamole/src/main/webapp/app/rest/services/tunnelService.js index 002965068..e736f82a7 100644 --- a/guacamole/src/main/webapp/app/rest/services/tunnelService.js +++ b/guacamole/src/main/webapp/app/rest/services/tunnelService.js @@ -43,6 +43,17 @@ angular.module('rest').factory('tunnelService', ['$injector', */ var document = $window.document; + /** + * The number of milliseconds to wait after a stream download has completed + * before cleaning up related DOM resources, if the browser does not + * otherwise notify us that cleanup is safe. + * + * @private + * @constant + * @type Number + */ + var DOWNLOAD_CLEANUP_WAIT = 5000; + /** * Makes a request to the REST API to get the list of all tunnels * associated with in-progress connections, returning a promise that @@ -189,6 +200,7 @@ angular.module('rest').factory('tunnelService', ['$injector', // Create temporary hidden iframe to facilitate download var iframe = document.createElement('iframe'); iframe.style.position = 'fixed'; + iframe.style.border = 'none'; iframe.style.width = '1px'; iframe.style.height = '1px'; iframe.style.left = '-1px'; @@ -197,11 +209,20 @@ angular.module('rest').factory('tunnelService', ['$injector', // The iframe MUST be part of the DOM for the download to occur document.body.appendChild(iframe); - // Automatically remove iframe from DOM when download completes - stream.onend = function downloadComplete() { + // Automatically remove iframe from DOM when download completes, if + // browser supports tracking of iframe downloads via the "load" event + iframe.onload = function downloadComplete() { document.body.removeChild(iframe); }; + // Automatically remove iframe from DOM a few seconds after the stream + // ends, in the browser does NOT fire the "load" event for downloads + stream.onend = function downloadComplete() { + $window.setTimeout(function cleanupIframe() { + document.body.removeChild(iframe); + }, DOWNLOAD_CLEANUP_WAIT); + }; + // Begin download iframe.src = url;