From 555d39c8486ddd5f50c9ddbb2a39cde5dacddf2e Mon Sep 17 00:00:00 2001 From: Max Nikulin Date: Wed, 23 Oct 2024 12:52:41 +0700 Subject: [PATCH] Make the webNavigation permission optional Capture quality may be silently degraded if the permission is not granted. No attempt to get active subframe is performed. --- README.org | 5 +++-- background/lr_settings.js | 17 +++++++++++++++++ background/lr_tabframe.js | 29 ++++++++++++++++++++++++----- manifest-chrome.json | 4 ++-- manifest-common.yaml | 2 +- manifest-firefox.json | 2 +- pages/lrp_help.html | 11 +++++++---- 7 files changed, 55 insertions(+), 15 deletions(-) diff --git a/README.org b/README.org index de81a9c..998a6e3 100644 --- a/README.org +++ b/README.org @@ -426,8 +426,9 @@ Chrome: "Read your browsing history". It is necessary to reliably restore tree of nested frames. Consider the case when some element is focused in a subframe and capture is invoked using keyboard shortcut. -Maybe I will add a less reliable fallback in future -to make this permission optional. +Another case is context menu invoked in a deeply nested frame. + +You may grant this permission on the extension options page.[fn:3] *** Access browser tabs (=tabs=) :PROPERTIES: diff --git a/background/lr_settings.js b/background/lr_settings.js index 02de16a..699793e 100644 --- a/background/lr_settings.js +++ b/background/lr_settings.js @@ -276,6 +276,23 @@ var lr_settings = lr_util.namespace(lr_settings, function lr_settings() { host: true, parent: "misc", }); + this.registerOption({ + name: "permissions.webNavigation", + title: 'Access browser activity during navigation ("webNavigation")', + version: "0.4", + description: [ + "Relevant to frames and embedded objects.", + "Without this permission the extension may be unable", + "to find active frame when invoked using", + "the toolbar button or the shortcut.", + "", + "Context menu is affected in less degree,", + "but capture info may still be incomplete", + "in the case of multiple level of nested frames." + ], + type: "permission", + parent: "misc", + }); }; this.load = async function() { diff --git a/background/lr_tabframe.js b/background/lr_tabframe.js index d79f640..3ad1ddc 100644 --- a/background/lr_tabframe.js +++ b/background/lr_tabframe.js @@ -40,6 +40,25 @@ var lr_tabframe = lr_util.namespace(lr_tabframe, function lr_tabframe() { }; } + lr_tabframe._hasWebNavigationPermission = async function _hasWebNavigationPermission() { + if (chrome.webNavigation?.getAllFrames === undefined) { + return false; + } + // Chromium-130 throws synchronously after `permissions.remove` + // chrome.webNavigation.getAllFrames({tabId: -1}) + // Error: 'webNavigation.getAllFrames' is not available in this context. + // + // If the permission is not available + // + // TypeError: Error in invocation of webNavigation.getAllFrames(object details, function callback): Error at parameter 'details': Error at property 'tabId': Value must be at least 0. + try { + return await bapi.permissions.contains({ permissions: [ "webNavigation" ] }); + } catch (ex) { + Promise.reject(ex); + } + return false; + } + Object.assign(this, { FORMAT, VERSION, makeCapture, @@ -147,7 +166,7 @@ function focusedFrameChain(frameMap) { async function lrGetAllFrames(tab) { // Likely redundant protection, tab should be valid here const tabId = tab != null ? tab.id : -1; - if (!(tabId >= 0)) { + if (!(tabId >= 0) || ! await lr_tabframe._hasWebNavigationPermission()) { // May happen in Chromium-87 when context menu is invoked for a PDF file // but should be handled by caller since element // in Chrome created for PDF file has its own "tab". @@ -515,12 +534,12 @@ async function lrGatherTabInfo(tab, clickData, activeTab, executor) { // allows to avoid noise due to e.g. empty `