File indexing completed on 2024-04-28 05:32:49
0001 /* 0002 Copyright (C) 2017-2019 Kai Uwe Broulik <kde@privat.broulik.de> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public License as 0006 published by the Free Software Foundation; either version 3 of 0007 the License, or (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 GNU General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program. If not, see <http://www.gnu.org/licenses/>. 0016 */ 0017 0018 var activeDownloads = [] 0019 var downloadUpdateInterval = 0; 0020 0021 function startSendingDownloadUpdates() { 0022 if (!chrome.downloads.onChanged.hasListener(onDownloadChanged)) { 0023 // Register this listener only when needed. If it's active during 0024 // browser startup, it can be triggered for existing downloads (also 0025 // no longer existing files!) and freeze the UI for >1min! 0026 chrome.downloads.onChanged.addListener(onDownloadChanged); 0027 } 0028 0029 if (!downloadUpdateInterval) { 0030 downloadUpdateInterval = setInterval(sendDownloadUpdates, 1000); 0031 } 0032 } 0033 0034 function stopSendingDownloadUpdates() { 0035 if (downloadUpdateInterval) { 0036 clearInterval(downloadUpdateInterval); 0037 downloadUpdateInterval = 0; 0038 } 0039 } 0040 0041 function sendDownloadUpdates() { 0042 chrome.downloads.search({ 0043 state: 'in_progress', 0044 paused: false 0045 }, function (results) { 0046 if (!results.length) { 0047 stopSendingDownloadUpdates(); 0048 return; 0049 } 0050 0051 results.forEach(function (download) { 0052 if (activeDownloads.indexOf(download.id) === -1) { 0053 return; 0054 } 0055 0056 var payload = { 0057 id: download.id, 0058 bytesReceived: download.bytesReceived, 0059 estimatedEndTime: download.estimatedEndTime, 0060 // Firefox ends along "-1" as totalBytes on download creation 0061 // but then never updates it, so we send this along periodically, too 0062 totalBytes: download.totalBytes 0063 }; 0064 0065 port.postMessage({subsystem: "downloads", event: "update", download: payload}); 0066 }); 0067 }); 0068 } 0069 0070 function createDownload(download) { 0071 // don't bother telling us about completed downloads... 0072 // otherwise on browser startup we'll spawn a gazillion download progress notification 0073 if (download.state === "complete" || download.state === "interrupted") { 0074 return; 0075 } 0076 0077 activeDownloads.push(download.id); 0078 startSendingDownloadUpdates(); 0079 0080 port.postMessage({subsystem: "downloads", event: "created", download: download}); 0081 } 0082 0083 function sendDownloads() { 0084 // When extension is (re)loaded, create each download initially 0085 chrome.downloads.search({ 0086 state: 'in_progress', 0087 }, function (results) { 0088 results.forEach(createDownload); 0089 }); 0090 } 0091 0092 chrome.downloads.onCreated.addListener(createDownload); 0093 0094 function onDownloadChanged(delta) { 0095 if (activeDownloads.indexOf(delta.id) === -1) { 0096 return; 0097 } 0098 0099 // An interrupted download was resumed. When a download is interrupted, we finish (and delete) 0100 // the job but the browser re-uses the existing download, so when this happen, 0101 // pretend a new download was created. 0102 if (delta.state) { 0103 if (delta.state.previous === "interrupted" && delta.state.current === "in_progress") { 0104 console.log("Resuming previously interrupted download, pretending a new download was created"); 0105 chrome.downloads.search({ 0106 id: delta.id 0107 }, function (downloads) { 0108 createDownload(downloads[0]); 0109 }); 0110 return; 0111 } 0112 } 0113 0114 // The update timer stops automatically when there are no running downloads 0115 // so make sure to restart it when a download is unpaused 0116 if (delta.paused) { 0117 if (delta.paused.previous && !delta.paused.current) { 0118 startSendingDownloadUpdates(); 0119 } 0120 } 0121 0122 var payload = {}; 0123 0124 Object.keys(delta).forEach((key) => { 0125 payload[key] = delta[key].current; 0126 }); 0127 0128 payload.id = delta.id; // not a delta, ie. has no current and thus isn't added by the loop below 0129 0130 port.postMessage({subsystem: "downloads", event: "update", download: payload}); 0131 }; 0132 0133 addCallback("downloads", "cancel", function (message) { 0134 var downloadId = message.downloadId; 0135 0136 console.log("Requested to cancel download", downloadId); 0137 0138 chrome.downloads.cancel(downloadId); 0139 }); 0140 0141 addCallback("downloads", "suspend", function (message) { 0142 var downloadId = message.downloadId; 0143 0144 console.log("Requested to suspend download", downloadId); 0145 0146 chrome.downloads.pause(downloadId); 0147 }); 0148 0149 addCallback("downloads", "resume", function (message) { 0150 var downloadId = message.downloadId; 0151 0152 console.log("Requested to resume download", downloadId); 0153 0154 chrome.downloads.resume(downloadId); 0155 }); 0156 0157 addCallback("downloads", "createAll", () => { 0158 sendDownloads(); 0159 });