diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts')
-rw-r--r-- | packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts b/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts new file mode 100644 index 000000000..838b47397 --- /dev/null +++ b/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts @@ -0,0 +1,135 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** + * This will modify all the pages that the user load when navigating with Web Extension enabled + * + * Can't do useful integration since it run in ISOLATED (or equivalent) mode. + * + * If taler support is expected, it will inject a script which will complete the integration. + */ + +// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities#content_script_environment + +// ISOLATED mode in chromium browsers +// https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md#world +// X-Ray vision in Firefox +// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts#xray_vision_in_firefox + +// *** IMPORTANT *** + +// Content script lifecycle during navigation +// In Firefox: Content scripts remain injected in a web page after the user has navigated away, +// however, window object properties are destroyed. +// In Chrome: Content scripts are destroyed when the user navigates away from a web page. + +const documentDocTypeIsHTML = + window.document.doctype && window.document.doctype.name === "html"; +const suffixIsNotXMLorPDF = + !window.location.pathname.endsWith(".xml") && + !window.location.pathname.endsWith(".pdf"); +const rootElementIsHTML = + document.documentElement.nodeName && + document.documentElement.nodeName.toLowerCase() === "html"; +const pageAcceptsTalerSupport = document.head.querySelector( + "meta[name=taler-support]", +); +// safe check, if one of this is true then taler handler is not useful +// or not expected +const shouldNotInject = + !documentDocTypeIsHTML || + !suffixIsNotXMLorPDF || + // !pageAcceptsTalerSupport || FIXME: removing this before release for testing + !rootElementIsHTML; +const logger = { + debug: (...msg: any[]) => {}, + info: (...msg: any[]) => + console.log(`${new Date().toISOString()} TALER`, ...msg), + error: (...msg: any[]) => + console.error(`${new Date().toISOString()} TALER`, ...msg), +}; + +function start() { + if (shouldNotInject) { + return; + } + const debugEnabled = + pageAcceptsTalerSupport?.getAttribute("debug") === "true"; + if (debugEnabled) { + logger.debug = logger.info; + } + createBridgeWithExtension(); + logger.debug("bridged created"); + injectTalerSupportScript(debugEnabled); + logger.debug("done"); +} + +/** + * Create a <script /> element that load the support in the page context. + * The interaction support script will create the API to send message + * that will be received by this loader and be redirected to the extension + * using the bridge. + */ +function injectTalerSupportScript(debugEnabled: boolean) { + const container = document.head || document.documentElement; + const scriptTag = document.createElement("script"); + + scriptTag.setAttribute("async", "false"); + const url = new URL( + chrome.runtime.getURL("/dist/taler-wallet-interaction-support.js"), + ); + url.searchParams.set("id", chrome.runtime.id); + if (debugEnabled) { + url.searchParams.set("debug", "true"); + } + scriptTag.src = url.href; + try { + container.insertBefore(scriptTag, container.children[0]); + } catch (e) { + logger.info("inserting link handler failed!"); + logger.error(e); + } +} + +/** + * Create a bridge connection between the page and the extension. + * + * Useful for API calls and replies. Not yet supported. + */ +function createBridgeWithExtension() { + const port = chrome.runtime.connect(); + + window.addEventListener( + "message", + (event) => { + logger.debug("message received", event); + if (event.source !== window) { + return; + } + if (event.origin !== window.origin) { + return; + } + + if (event.data.type && event.data.type === "FROM_PAGE") { + logger.debug("Content script received: " + event.data.text); + port.postMessage(event.data.text); + } + }, + false, + ); +} + +start(); |