2 Copyright (C) 2017-2019 Kai Uwe Broulik <kde@privat.broulik.de>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 3 of
7 the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 var activeDownloads = []
19 var downloadUpdateInterval = 0;
21 function startSendingDownloadUpdates() {
22 if (!downloadUpdateInterval) {
23 downloadUpdateInterval = setInterval(sendDownloadUpdates, 1000);
27 function stopSendingDownloadUpdates() {
28 if (downloadUpdateInterval) {
29 clearInterval(downloadUpdateInterval);
30 downloadUpdateInterval = 0;
34 function sendDownloadUpdates() {
35 chrome.downloads.search({
38 }, function (results) {
39 if (!results.length) {
40 stopSendingDownloadUpdates();
44 results.forEach(function (download) {
45 if (activeDownloads.indexOf(download.id) === -1) {
51 bytesReceived: download.bytesReceived,
52 estimatedEndTime: download.estimatedEndTime,
53 // Firefox ends along "-1" as totalBytes on download creation
54 // but then never updates it, so we send this along periodically, too
55 totalBytes: download.totalBytes
58 port.postMessage({subsystem: "downloads", event: "update", download: payload});
63 function createDownload(download) {
64 // don't bother telling us about completed downloads...
65 // otherwise on browser startup we'll spawn a gazillion download progress notification
66 if (download.state === "complete" || download.state === "interrupted") {
70 activeDownloads.push(download.id);
71 startSendingDownloadUpdates();
73 port.postMessage({subsystem: "downloads", event: "created", download: download});
76 function sendDownloads() {
77 // When extension is (re)loaded, create each download initially
78 chrome.downloads.search({
80 }, function (results) {
81 results.forEach(createDownload);
85 chrome.downloads.onCreated.addListener(createDownload);
87 chrome.downloads.onChanged.addListener(function (delta) {
88 if (activeDownloads.indexOf(delta.id) === -1) {
92 // An interrupted download was resumed. When a download is interrupted, we finish (and delete)
93 // the job but the browser re-uses the existing download, so when this happen,
94 // pretend a new download was created.
96 if (delta.state.previous === "interrupted" && delta.state.current === "in_progress") {
97 console.log("Resuming previously interrupted download, pretending a new download was created");
98 chrome.downloads.search({
100 }, function (downloads) {
101 createDownload(downloads[0]);
107 // The update timer stops automatically when there are no running downloads
108 // so make sure to restart it when a download is unpaused
110 if (delta.paused.previous && !delta.paused.current) {
111 startSendingDownloadUpdates();
117 Object.keys(delta).forEach((key) => {
118 payload[key] = delta[key].current;
121 payload.id = delta.id; // not a delta, ie. has no current and thus isn't added by the loop below
123 port.postMessage({subsystem: "downloads", event: "update", download: payload});
126 addCallback("downloads", "cancel", function (message) {
127 var downloadId = message.downloadId;
129 console.log("Requested to cancel download", downloadId);
131 chrome.downloads.cancel(downloadId);
134 addCallback("downloads", "suspend", function (message) {
135 var downloadId = message.downloadId;
137 console.log("Requested to suspend download", downloadId);
139 chrome.downloads.pause(downloadId);
142 addCallback("downloads", "resume", function (message) {
143 var downloadId = message.downloadId;
145 console.log("Requested to resume download", downloadId);
147 chrome.downloads.resume(downloadId);
150 addCallback("downloads", "createAll", () => {