aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-04-13 12:19:00 -0300
committerSebastian <sebasjm@gmail.com>2023-04-13 12:57:39 -0300
commitebd004195673c58718c7c9d8b8270df28b35b539 (patch)
treea3331d68cb650f2945df82539c7b7a1578bbf0be /packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts
parent2baa42f22346be1a1baafb96ba8b5169da8db83c (diff)
downloadwallet-core-ebd004195673c58718c7c9d8b8270df28b35b539.tar.xz
taler wallet interaction support, first version
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.ts135
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();