From 8d4a5e5301dd70e270ff5b2f03cc3c6346e9fb23 Mon Sep 17 00:00:00 2001 From: GChristensen Date: Tue, 7 Jun 2022 17:57:46 +0400 Subject: [PATCH] finished porting to manifest v3 --- README.md | 6 ++++ addon/backend_native.js | 7 ++++- addon/bookmarking.js | 9 ++++-- addon/core.js | 35 ++++++++++++++++++----- addon/manifest.json | 2 +- addon/{mv3_fixup.js => mv3_persistent.js} | 9 +++--- addon/savepage/background.js | 2 +- addon/ui/popup.js | 4 ++- addon/utils_browser.js | 20 +++++++++++++ 9 files changed, 75 insertions(+), 19 deletions(-) rename addon/{mv3_fixup.js => mv3_persistent.js} (76%) diff --git a/README.md b/README.md index 9bf4928..e7c6ec8 100644 --- a/README.md +++ b/README.md @@ -45,3 +45,9 @@ the [online help](https://gchristensen.github.io/scrapyard/addon/ui/locales/en/h * [DONE] Add ability to browser synchronized bookmarks to the android application * [DONE] Add ability to capture entire sites a la WebScrapBook * [DONE] Add ability to undo bookmark deletions + +### Manifest v3 Status + +The addon is succesfully ported to the manifest v3 as it is +[implemented](https://extensionworkshop.com/documentation/develop/manifest-v3-migration-guide/) +in Firefox Nightly v102. To run with MV3 rename manifest.json.mv3 to manifest.json. diff --git a/addon/backend_native.js b/addon/backend_native.js index c7fe675..d053738 100644 --- a/addon/backend_native.js +++ b/addon/backend_native.js @@ -1,6 +1,6 @@ import UUID from "./lib/uuid.js" import {settings} from "./settings.js" -import {showNotification} from "./utils_browser.js"; +import {hasCSRPermission, showNotification} from "./utils_browser.js"; class NativeBackend { constructor() { @@ -55,9 +55,14 @@ class NativeBackend { } async probe(verbose = false) { + if (!await hasCSRPermission()) + return false; + const port = await this.getPort(); + if (!port && verbose) showNotification({message: "Can not connect to the helper application."}) + return !!port; } diff --git a/addon/bookmarking.js b/addon/bookmarking.js index 36e8b88..1f92078 100644 --- a/addon/bookmarking.js +++ b/addon/bookmarking.js @@ -1,6 +1,6 @@ import {settings} from "./settings.js"; import { - getActiveTab, injectCSSFile, injectScriptFile, + getActiveTab, hasCSRPermission, injectCSSFile, injectScriptFile, openContainerTab, openPage, scriptsAllowed, @@ -141,6 +141,9 @@ function startSavePageCapture(tab, bookmark, selection) { } async function injectSavePageScripts(tab, onError) { + if (!await hasCSRPermission()) + return; + try { try { await injectScriptFile(tab.id, {file: "/savepage/content-frame.js", allFrames: true}); @@ -356,8 +359,8 @@ function configureArchiveTab(node, archiveTab) { async function configureArchivePage(tab, node) { if (archiveTabs[tab.id]?.has(tab.url.replace(/#.*$/, ""))) { await injectCSSFile(tab.id, {file: "ui/edit_toolbar.css"}); - await injectScriptFile(tab.id, {file: "lib/jquery.js"}); - await injectScriptFile(tab.id, {file: "ui/edit_toolbar.js"}); + await injectScriptFile(tab.id, {file: "lib/jquery.js", frameId: 0}); + await injectScriptFile(tab.id, {file: "ui/edit_toolbar.js", frameId: 0}); if (settings.open_bookmark_in_active_tab()) node = await Node.getByUUID(tab.url.replace(/^.*#/, "").split(":")[0]) diff --git a/addon/core.js b/addon/core.js index 339effb..b46e3d7 100644 --- a/addon/core.js +++ b/addon/core.js @@ -16,9 +16,10 @@ import * as repair from "./core_maintenance.js"; import * as ishell from "./core_ishell.js"; import * as automation from "./core_automation.js"; import * as sync from "./core_sync.js"; +import {askCSRPermission} from "./utils_browser.js"; if (_MANIFEST_V3) - import("./mv3_fixup.js"); + import("./mv3_persistent.js"); browser.runtime.onInstalled.addListener(async details => { await settings.load(); @@ -36,13 +37,21 @@ receiveExternal.startListener(true); receive.startListener(true); (async () => { - await systemInitialization; - if (await navigator.storage.persist()) { - // TODO: in MV3 somehow this should be done only once on the addon load - await performStartupInitialization(); + await systemInitialization; + + if (_MANIFEST_V3) { + // until there is no storage.local API, + // use an alarm as a flag to call initialization function only once + const alarm = await browser.alarms.get("startup-flag-alarm"); - console.log("==> core.js loaded"); + if (!alarm) { + await performStartupInitialization(); + browser.alarms.create("startup-flag-alarm", {periodInMinutes: 525960}); // one year + } + } + else + await performStartupInitialization(); } })(); @@ -59,6 +68,8 @@ async function performStartupInitialization() { sendLocal.performSync(); await UndoManager.commit(); + + console.log("==> core.js initialized"); } browser.webRequest.onBeforeSendHeaders.addListener( @@ -86,7 +97,15 @@ browser.commands.onCommand.addListener(function(command) { browser.sidebarAction.open(); } - addBookmark(action); + if (action === "createArchive") + askCSRPermission() + .then(response => { + if (response) + addBookmark(action); + }) + .catch(e => console.error(e)); + else + addBookmark(action); }); async function addBookmark(event) { @@ -95,3 +114,5 @@ async function addBookmark(event) { return sendLocal[event]({node: payload}); } + +console.log("==> core.js loaded"); diff --git a/addon/manifest.json b/addon/manifest.json index 570444a..05f3bf1 100644 --- a/addon/manifest.json +++ b/addon/manifest.json @@ -1,5 +1,5 @@ { - "version": "0.17.4.7", + "version": "1.0", "applications": { "gecko": { "id": "scrapyard@firefox", diff --git a/addon/mv3_fixup.js b/addon/mv3_persistent.js similarity index 76% rename from addon/mv3_fixup.js rename to addon/mv3_persistent.js index cd76440..d47ec9f 100644 --- a/addon/mv3_fixup.js +++ b/addon/mv3_persistent.js @@ -1,5 +1,4 @@ // permanently keeps the background page in memory -// works only if blob/http(s) tabs are present // adapted from https://stackoverflow.com/questions/66618136/persistent-service-worker-in-chrome-extension let lifeline; @@ -7,7 +6,7 @@ let lifeline; keepAlive(); browser.runtime.onConnect.addListener(port => { - if (port.name === 'keepAlive') { + if (port.name === "keepAlive") { lifeline = port; setTimeout(keepAliveForced, 25000); // 25 seconds port.onDisconnect.addListener(keepAliveForced); @@ -23,11 +22,11 @@ function keepAliveForced() { async function keepAlive() { if (lifeline) return; - for (const tab of await browser.tabs.query({ url: '*://*/*' })) { + for (const tab of await browser.tabs.query({})) { try { await browser.scripting.executeScript({ target: { tabId: tab.id }, - func: () => browser.runtime.connect({ name: 'keepAlive' }), + func: () => browser.runtime.connect({ name: "keepAlive" }), }); browser.tabs.onUpdated.removeListener(retryOnTabUpdate); return; @@ -37,7 +36,7 @@ async function keepAlive() { } async function retryOnTabUpdate(tabId, info, tab) { - if (info.url && /^(blob|https?):/.test(info.url)) { + if (info.url && /^(about|blob|https?):/.test(info.url)) { keepAlive(); } } diff --git a/addon/savepage/background.js b/addon/savepage/background.js index 7bdcdaf..65c7894 100644 --- a/addon/savepage/background.js +++ b/addon/savepage/background.js @@ -763,7 +763,7 @@ function addListeners() /* Messages from content script */ // Scrapyard ////////////////////////////////////////////////////////////////// - case "SAVEPAGE_SETTINGS_CHANGED": + case "savepageSettingsChanged": initialize(true); break; ////////////////////////////////////////////////////////////////// Scrapyard // diff --git a/addon/ui/popup.js b/addon/ui/popup.js index 0410e7d..b4eedcf 100644 --- a/addon/ui/popup.js +++ b/addon/ui/popup.js @@ -5,6 +5,7 @@ import {send} from "../proxy.js"; import {selectricRefresh, simpleSelectric} from "./shelf_list.js"; import {Query} from "../storage_query.js"; import {systemInitialization} from "../bookmarks_init.js"; +import {askCSRPermission} from "../utils_browser.js"; let tree; @@ -135,7 +136,8 @@ window.onload = async function () { }); $("#create-archive").on("click", async e => { - await addBookmark(NODE_TYPE_ARCHIVE); + if (await askCSRPermission()) + await addBookmark(NODE_TYPE_ARCHIVE); window.close(); }); diff --git a/addon/utils_browser.js b/addon/utils_browser.js index d0e9e17..fb8d590 100644 --- a/addon/utils_browser.js +++ b/addon/utils_browser.js @@ -88,3 +88,23 @@ export const CONTEXT_FOREGROUND = 1; export function getContextType() { return window.location.pathname === "/background.html"? CONTEXT_BACKGROUND: CONTEXT_FOREGROUND; } + +export async function askCSRPermission() { + if (_MANIFEST_V3) + return browser.permissions.request({origins: [""]}); + + return true; +} + +export async function hasCSRPermission(verbose = true) { + if (_MANIFEST_V3) { + const response = await browser.permissions.contains({origins: [""]}); + + if (!response && verbose) + showNotification("Please, enable optional add-on permissions at the Firefox add-on settings page (about:addons)."); + + return response; + } + + return true; +}