'use strict'; var electron = require('electron'); var extName = require('ext-name'); var path = require('path'); var fs = require('fs'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol */ function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; let { online } = electron.net; let timer; const listeners = { online: new Set(), offline: new Set() }; function addNetListener(onLine, onOffline) { return __awaiter(this, void 0, void 0, function* () { if (!timer) { timer = setInterval(() => { const isOnline = electron.net.online; if (online === isOnline) return; listeners[isOnline ? 'online' : 'offline'].forEach(fn => fn()); online = isOnline; }, 1000); } yield electron.app.whenReady(); listeners.online.add(onLine); listeners.offline.add(onOffline); return [ () => listeners.online.delete(onLine), () => listeners.offline.delete(onOffline) ]; }); } var NetStatus; (function (NetStatus) { NetStatus["Online"] = "online"; NetStatus["Offline"] = "offline"; })(NetStatus || (NetStatus = {})); class CancelError extends Error { } // @ts-ignore function getFilenameFromMime(name, mime) { const extensions = extName.mime(mime); if (extensions.length !== 1) { return name; } return `${name}.${extensions[0].ext}`; } function unusedFilename(filepath) { const dirname = path__namespace.dirname(filepath); const basename = path__namespace.basename(filepath, path__namespace.extname(filepath)); const extname = path__namespace.extname(filepath); let count = 1; let newFilePath = filepath; // 生成新的文件路径,直到找到一个不存在的路径 while (fs.existsSync(newFilePath)) { newFilePath = path__namespace.join(dirname, `${basename} (${count})${extname}`); count++; } return newFilePath; } function majorElectronVersion() { const version = process.versions.electron.split('.'); return Number.parseInt(version[0], 10); } function getWindowFromBrowserView(webContents) { for (const currentWindow of electron.BrowserWindow.getAllWindows()) { for (const currentBrowserView of currentWindow.getBrowserViews()) { if (currentBrowserView.webContents.id === webContents.id) { return currentWindow; } } } return undefined; } function getWindowFromWebContents(webContents) { let window; const webContentsType = webContents.getType(); switch (webContentsType) { case 'webview': window = electron.BrowserWindow.fromWebContents(webContents.hostWebContents); break; case 'browserView': window = getWindowFromBrowserView(webContents); break; default: window = electron.BrowserWindow.fromWebContents(webContents); break; } return window; } const sessions = new WeakSet(); const downloadItems = new Map(); let receivedBytes = 0; let totalBytes = 0; const activeDownloadItems = () => downloadItems.size; const progressDownloadItems = () => receivedBytes / totalBytes; addNetListener(() => { for (const item of downloadItems.keys()) { !item.isPaused() && item.resume(); } }, () => { }); function listener(_, item, webContents, callback) { const options = downloadItems.get(item); if (!options) return; const errorMessage = options.errorMessage || 'The download of {filename} was interrupted'; const window = majorElectronVersion() >= 12 ? electron.BrowserWindow.fromWebContents(webContents) : getWindowFromWebContents(webContents); item.on('updated', () => { totalBytes = 0; receivedBytes = 0; for (const item of downloadItems.keys()) { receivedBytes += item.getReceivedBytes(); totalBytes += item.getTotalBytes(); } if (options.showBadge && ['darwin', 'linux'].includes(process.platform)) { electron.app.badgeCount = activeDownloadItems(); } if (window && !window.isDestroyed() && options.showProgressBar) { window.setProgressBar(progressDownloadItems()); } if (typeof options.onProgress === 'function') { const itemTransferredBytes = item.getReceivedBytes(); const itemTotalBytes = item.getTotalBytes(); options.onProgress({ percent: itemTotalBytes ? itemTransferredBytes / itemTotalBytes : 0, transferredBytes: itemTransferredBytes, totalBytes: itemTotalBytes }, item); } if (typeof options.onTotalProgress === 'function') { options.onTotalProgress({ percent: progressDownloadItems(), transferredBytes: receivedBytes, totalBytes }, item); } }); item.on('done', (_, state) => { downloadItems.delete(item); if (options.showBadge && ['darwin', 'linux'].includes(process.platform)) { electron.app.badgeCount = activeDownloadItems(); } if (window && !window.isDestroyed() && !activeDownloadItems()) { window.setProgressBar(-1); receivedBytes = 0; totalBytes = 0; } if (state === 'cancelled') { downloadItems.delete(item); if (typeof options.onCancel === 'function') { options.onCancel(item); } callback(new CancelError(), item); } else if (state === 'interrupted') { callback(new Error(errorMessage), item); } else if (state === 'completed') { downloadItems.delete(item); const savePath = item.getSavePath(); if (process.platform === 'darwin') { electron.app.dock.downloadFinished(savePath); } if (options.openFolderWhenDone) { electron.shell.showItemInFolder(savePath); } if (typeof options.onCompleted === 'function') { options.onCompleted({ filename: item.getFilename(), path: savePath, fileSize: item.getReceivedBytes(), mimeType: item.getMimeType(), url: item.getURL() }, item); } callback(null, item); } }); if (typeof options.onStarted === 'function') { options.onStarted(item); } } function registerListener(session, options, callback = () => { }) { options = Object.assign({ showBadge: true, showProgressBar: true }, options); const setOption = (_, item) => { downloadItems.set(item, options); if (options.directory && !path__namespace.isAbsolute(options.directory)) { throw new Error('The `directory` option must be an absolute path'); } const directory = options.directory || electron.app.getPath('downloads'); let filePath; if (options.filename) { filePath = path__namespace.join(directory, options.filename); } else { const filename = item.getFilename(); const name = path__namespace.extname(filename) ? filename : getFilenameFromMime(filename, item.getMimeType()); filePath = options.overwrite ? path__namespace.join(directory, name) : unusedFilename(path__namespace.join(directory, name)); } if (options.saveAs) { item.setSaveDialogOptions(Object.assign({ defaultPath: filePath }, options.dialogOptions)); } else { item.setSavePath(filePath); } session.off('will-download', setOption); }; session.on('will-download', setOption); if (sessions.has(session)) { return; } sessions.add(session); session.on('will-download', (_, item, webContents) => setTimeout(() => listener(_, item, webContents, callback), 0)); } function download(window, url, options = {}) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { options = Object.assign({}, options); registerListener(window.webContents.session, options, (error, item) => { if (error) { reject(error); } else { resolve(item); } }); window.webContents.downloadURL(url); }); }); } exports.download = download;