| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /*
- * Copyright 2010-2020 Gildas Lormeau
- * contact : gildas.lormeau <at> gmail.com
- *
- * This file is part of SingleFile.
- *
- * The code in this file is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * (GNU AGPL) as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * The code in this file 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 Affero
- * General Public License for more details.
- *
- * As additional permission under GNU AGPL version 3 section 7, you may
- * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
- * AGPL normally required by section 4, provided you include this license
- * notice and a URL through which recipients can access the Corresponding
- * Source.
- */
- /* global infobar, URL, Blob, XMLHttpRequest */
- import * as config from "./config.js";
- import * as business from "./business.js";
- import * as companion from "./companion.js";
- import * as downloads from "./downloads.js";
- import * as tabsData from "./tabs-data.js";
- import * as tabs from "./tabs.js";
- import * as ui from "./../../ui/bg/index.js";
- import { getPageData } from "./../../index.js";
- import * as woleet from "./../../lib/woleet/woleet.js";
- export {
- onMessage,
- onMessageExternal,
- onInit,
- isEnabled,
- refreshTabs
- };
- async function onMessage(message, sender) {
- if (message.method.endsWith(".init")) {
- const [options, autoSaveEnabled] = await Promise.all([config.getOptions(sender.tab.url, true), isEnabled(sender.tab)]);
- return { options, autoSaveEnabled };
- }
- if (message.method.endsWith(".save")) {
- const tabId = sender.tab.id;
- const options = await config.getOptions(sender.tab.url, true);
- if (options) {
- ui.onStart(tabId, 1, true);
- await saveContent(message, sender.tab);
- ui.onEnd(tabId, true);
- }
- return {};
- }
- }
- async function onMessageExternal(message, currentTab) {
- if (message.method == "enableAutoSave") {
- const allTabsData = await tabsData.get(currentTab.id);
- allTabsData[currentTab.id].autoSave = message.enabled;
- await tabsData.set(allTabsData);
- ui.refreshTab(currentTab);
- }
- if (message.method == "isAutoSaveEnabled") {
- return isEnabled(currentTab);
- }
- }
- async function onInit(tab) {
- const [options, autoSaveEnabled] = await Promise.all([config.getOptions(tab.url, true), isEnabled(tab)]);
- if (options && ((options.autoSaveLoad || options.autoSaveLoadOrUnload) && autoSaveEnabled)) {
- business.saveTabs([tab], { autoSave: true });
- }
- }
- async function isEnabled(tab) {
- if (tab) {
- const [allTabsData, rule] = await Promise.all([tabsData.get(), config.getRule(tab.url)]);
- return Boolean(allTabsData.autoSaveAll ||
- (allTabsData.autoSaveUnpinned && !tab.pinned) ||
- (allTabsData[tab.id] && allTabsData[tab.id].autoSave)) &&
- (!rule || rule.autoSaveProfile != config.DISABLED_PROFILE_NAME);
- }
- }
- async function refreshTabs() {
- const allTabs = (await tabs.get({}));
- return Promise.all(allTabs.map(async tab => {
- const [options, autoSaveEnabled] = await Promise.all([config.getOptions(tab.url, true), isEnabled(tab)]);
- try {
- await tabs.sendMessage(tab.id, { method: "content.init", autoSaveEnabled, options });
- } catch (error) {
- // ignored
- }
- }));
- }
- async function saveContent(message, tab) {
- const options = await config.getOptions(tab.url, true);
- const tabId = tab.id;
- options.content = message.content;
- options.url = message.url;
- options.frames = message.frames;
- options.canvases = message.canvases;
- options.fonts = message.fonts;
- options.stylesheets = message.stylesheets;
- options.images = message.images;
- options.posters = message.posters;
- options.usedFonts = message.usedFonts;
- options.shadowRoots = message.shadowRoots;
- options.imports = message.imports;
- options.referrer = message.referrer;
- options.updatedResources = message.updatedResources;
- options.visitDate = new Date(message.visitDate);
- options.backgroundTab = true;
- options.autoSave = true;
- options.incognito = tab.incognito;
- options.tabId = tabId;
- options.tabIndex = tab.index;
- let pageData;
- try {
- if (options.autoSaveExternalSave) {
- await companion.save(options);
- } else {
- pageData = await getPageData(options, null, null, { fetch });
- if (options.includeInfobar) {
- await infobar.includeScript(pageData);
- }
- const blob = new Blob([pageData.content], { type: "text/html" });
- if (options.saveToGDrive) {
- await downloads.uploadPage(message.taskId, pageData.filename, blob, options, {});
- } else {
- pageData.url = URL.createObjectURL(blob);
- await downloads.downloadPage(pageData, options);
- }
- if (pageData.hash) {
- await woleet.anchor(pageData.hash);
- }
- }
- } finally {
- business.onSaveEnd(message.taskId);
- if (pageData && pageData.url) {
- URL.revokeObjectURL(pageData.url);
- }
- }
- }
- function fetch(url) {
- return new Promise((resolve, reject) => {
- const xhrRequest = new XMLHttpRequest();
- xhrRequest.withCredentials = true;
- xhrRequest.responseType = "arraybuffer";
- xhrRequest.onerror = event => reject(new Error(event.detail));
- xhrRequest.onreadystatechange = () => {
- if (xhrRequest.readyState == XMLHttpRequest.DONE) {
- resolve({
- status: xhrRequest.status,
- headers: {
- get: name => xhrRequest.getResponseHeader(name)
- },
- arrayBuffer: async () => xhrRequest.response
- });
- }
- };
- xhrRequest.open("GET", url, true);
- xhrRequest.send();
- });
- }
|