| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /*
- * Copyright 2018 Gildas Lormeau
- * contact : gildas.lormeau <at> gmail.com
- *
- * This file is part of SingleFile.
- *
- * SingleFile is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * SingleFile is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with SingleFile. If not, see <http://www.gnu.org/licenses/>.
- */
- /* global browser, SingleFile, singlefile, Blob */
- singlefile.core = (() => {
- const FORBIDDEN_URLS = ["https://chrome.google.com", "https://addons.mozilla.org"];
- const contentScriptFiles = [
- "/lib/browser-polyfill/custom-browser-polyfill.js",
- "/lib/single-file/doc-helper.js",
- "/lib/single-file/base64.js",
- "/lib/single-file/parse-srcset.js",
- "/lib/fetch/content/fetch.js",
- "/lib/single-file/single-file-core.js",
- "/lib/single-file/single-file-browser.js",
- "/extension/index.js",
- "/extension/ui/content/content-ui.js",
- "/extension/core/content/content.js"
- ];
- const frameScriptFiles = [
- "/lib/browser-polyfill/custom-browser-polyfill.js",
- "/extension/index.js",
- "/lib/single-file/doc-helper.js",
- "/lib/single-file/timeout.js",
- "/lib/single-file/frame-tree.js",
- "/extension/core/content/content-frame.js"
- ];
- const optionalContentScriptFiles = {
- compressHTML: [
- "/lib/single-file/htmlmini.js",
- "/lib/single-file/serializer.js"
- ],
- compressCSS: [
- "/lib/single-file/uglifycss.js"
- ],
- removeAlternativeFonts: [
- "/lib/single-file/fonts-minifier.js"
- ],
- removeUnusedStyles: [
- "/lib/single-file/css-what.js",
- "/lib/single-file/parse-css.js",
- "/lib/single-file/rules-matcher.js",
- "/lib/single-file/css-minifier.js"
- ],
- lazyLoadImages: [
- "/lib/single-file/lazy-loader.js",
- ]
- };
- browser.runtime.onMessage.addListener((request, sender) => {
- if (request.getConfig) {
- return singlefile.config.get();
- }
- if (request.processContent) {
- processBackgroundTab(sender.tab, request);
- }
- });
- browser.tabs.onRemoved.addListener(async tabId => {
- const tabsData = await singlefile.storage.get();
- delete tabsData[tabId];
- await singlefile.storage.set(tabsData);
- });
- return { saveTab, autoSaveTab, isAllowedURL };
- async function saveTab(tab, processOptions) {
- const options = await singlefile.config.get();
- Object.keys(processOptions).forEach(key => options[key] = processOptions[key]);
- return new Promise(async (resolve, reject) => {
- const processPromise = saveStart(tab, options);
- try {
- await processPromise;
- } catch (error) {
- reject(error);
- }
- resolve();
- });
- }
- async function autoSaveTab(tab) {
- const options = await singlefile.config.get();
- return new Promise(async (resolve, reject) => {
- const processPromise = autoSaveStart(tab, options);
- try {
- await processPromise;
- } catch (error) {
- reject(error);
- }
- resolve();
- });
- }
- function isAllowedURL(url) {
- return url && (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("file://")) && !FORBIDDEN_URLS.find(storeUrl => url.startsWith(storeUrl));
- }
- async function processBackgroundTab(tab, message) {
- const options = await singlefile.config.get();
- options.content = message.content;
- options.url = message.url;
- options.framesData = message.framesData;
- options.canvasData = message.canvasData;
- options.stylesheetContents = message.stylesheetContents;
- options.imageData = message.imageData;
- options.insertSingleFileComment = true;
- options.insertFaviconLink = true;
- options.backgroundTab = true;
- options.autoSave = true;
- options.incognito = tab.incognito;
- let index = 0, maxIndex = 0;
- options.onprogress = async event => {
- if (event.type == event.RESOURCES_INITIALIZED) {
- maxIndex = event.details.max;
- }
- if (event.type == event.RESOURCES_INITIALIZED || event.type == event.RESOURCE_LOADED) {
- index++;
- singlefile.ui.button.onProgress(tab.id, index, maxIndex, { autoSave: true });
- } else if (event.type == event.PAGE_ENDED) {
- singlefile.ui.button.onEnd(tab.id, { autoSave: true });
- }
- };
- const processor = new (SingleFile.getClass())(options);
- await processor.initialize();
- await processor.preparePageData();
- const page = processor.getPageData();
- const date = new Date();
- page.filename = page.title + (options.appendSaveDate ? " (" + date.toISOString().split("T")[0] + " " + date.toLocaleTimeString() + ")" : "") + ".html";
- page.url = URL.createObjectURL(new Blob([page.content], { type: "text/html" }));
- return singlefile.download.downloadPage(page, options);
- }
- async function saveStart(tab, options) {
- if (!options.removeFrames) {
- await executeScripts(tab.id, frameScriptFiles, true);
- }
- await executeScripts(tab.id, getContentScriptFiles(options), false);
- if (options.frameId) {
- await browser.tabs.sendMessage(tab.id, { saveFrame: true, options }, { frameId: options.frameId });
- } else {
- await browser.tabs.sendMessage(tab.id, { savePage: true, options });
- }
- }
- async function autoSaveStart(tab, options) {
- await browser.tabs.sendMessage(tab.id, { autoSavePage: true, options });
- }
- async function executeScripts(tabId, scriptFiles, allFrames) {
- return Promise.all(scriptFiles.map(file => browser.tabs.executeScript(tabId, { file, allFrames })));
- }
- function getContentScriptFiles(options) {
- let files = contentScriptFiles;
- Object.keys(optionalContentScriptFiles).forEach(option => {
- if (options[option]) {
- files = optionalContentScriptFiles[option].concat(files);
- }
- });
- return files;
- }
- })();
|