gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 03/03: fix: 6964


From: gnunet
Subject: [taler-wallet-core] 03/03: fix: 6964
Date: Fri, 29 Apr 2022 20:49:32 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

commit 5e7be5865888393fbf3e00ed76a556bb4f0ace66
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Apr 29 15:48:35 2022 -0300

    fix: 6964
    
    update icon when there is an taler action present
---
 .../taler-wallet-webextension/manifest-v2.json     |   8 +-
 .../taler-wallet-webextension/manifest-v3.json     |   3 +-
 .../src/platform/chrome.ts                         | 244 +++++++++++++++++----
 3 files changed, 207 insertions(+), 48 deletions(-)

diff --git a/packages/taler-wallet-webextension/manifest-v2.json 
b/packages/taler-wallet-webextension/manifest-v2.json
index da00d6d8..d3c346a0 100644
--- a/packages/taler-wallet-webextension/manifest-v2.json
+++ b/packages/taler-wallet-webextension/manifest-v2.json
@@ -33,12 +33,12 @@
   },
   "permissions": [
     "unlimitedStorage",
+    "http://*/*";,
+    "https://*/*";,
     "activeTab"
   ],
   "optional_permissions": [
-    "webRequest",
-    "http://*/*";,
-    "https://*/*";
+    "webRequest"
   ],
   "browser_action": {
     "default_icon": {
@@ -59,4 +59,4 @@
     "page": "static/background.html",
     "persistent": true
   }
-}
+}
\ No newline at end of file
diff --git a/packages/taler-wallet-webextension/manifest-v3.json 
b/packages/taler-wallet-webextension/manifest-v3.json
index 6d32f157..21c6b337 100644
--- a/packages/taler-wallet-webextension/manifest-v3.json
+++ b/packages/taler-wallet-webextension/manifest-v3.json
@@ -21,6 +21,7 @@
     "unlimitedStorage",
     "activeTab",
     "scripting",
+    "declarativeContent",
     "alarms"
   ],
   "commands": {
@@ -55,4 +56,4 @@
   "background": {
     "service_worker": "dist/background.js"
   }
-}
+}
\ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts 
b/packages/taler-wallet-webextension/src/platform/chrome.ts
index be7dd40f..ef8904b7 100644
--- a/packages/taler-wallet-webextension/src/platform/chrome.ts
+++ b/packages/taler-wallet-webextension/src/platform/chrome.ts
@@ -46,7 +46,7 @@ export default api;
 const logger = new Logger("chrome.ts");
 
 function keepAlive(callback: any): void {
-  if (chrome.runtime && chrome.runtime.getManifest().manifest_version === 3) {
+  if (extensionIsManifestV3()) {
     chrome.alarms.create("wallet-worker", { periodInMinutes: 1 })
 
     chrome.alarms.onAlarm.addListener((a) => {
@@ -122,7 +122,7 @@ export async function removeHostPermissions(): 
Promise<boolean> {
     });
   }
 
-  if (chrome.runtime && chrome.runtime.getManifest().manifest_version === 3) {
+  if (extensionIsManifestV3()) {
     // Trying to remove host permissions with manifest >= v3 throws an error
     return true;
   }
@@ -156,7 +156,7 @@ function getPermissionsApi(): CrossBrowserPermissionsApi {
  * @param callback function to be called
  */
 function notifyWhenAppIsReady(callback: () => void): void {
-  if (chrome.runtime && chrome.runtime.getManifest().manifest_version === 3) {
+  if (extensionIsManifestV3()) {
     callback()
   } else {
     window.addEventListener("load", callback);
@@ -356,21 +356,165 @@ function registerTalerHeaderListener(callback: (tabId: 
number, url: string) => v
   });
 }
 
+const alertIcons = {
+  "16": "/static/img/taler-alert-16.png",
+  "19": "/static/img/taler-alert-19.png",
+  "32": "/static/img/taler-alert-32.png",
+  "38": "/static/img/taler-alert-38.png",
+  "48": "/static/img/taler-alert-48.png",
+  "64": "/static/img/taler-alert-64.png",
+  "128": "/static/img/taler-alert-128.png",
+  "256": "/static/img/taler-alert-256.png",
+  "512": "/static/img/taler-alert-512.png"
+}
+const normalIcons = {
+  "16": "/static/img/taler-logo-16.png",
+  "19": "/static/img/taler-logo-19.png",
+  "32": "/static/img/taler-logo-32.png",
+  "38": "/static/img/taler-logo-38.png",
+  "48": "/static/img/taler-logo-48.png",
+  "64": "/static/img/taler-logo-64.png",
+  "128": "/static/img/taler-logo-128.png",
+  "256": "/static/img/taler-logo-256.png",
+  "512": "/static/img/taler-logo-512.png"
+}
+function setNormalIcon(): void {
+  if (extensionIsManifestV3()) {
+    chrome.action.setIcon({ path: normalIcons })
+  } else {
+    chrome.browserAction.setIcon({ path: normalIcons })
+  }
+}
+
+function setAlertedIcon(): void {
+  if (extensionIsManifestV3()) {
+    chrome.action.setIcon({ path: alertIcons })
+  } else {
+    chrome.browserAction.setIcon({ path: alertIcons })
+  }
+}
+
+
+interface OffscreenCanvasRenderingContext2D extends CanvasState, 
CanvasTransform, CanvasCompositing, CanvasImageSmoothing, 
CanvasFillStrokeStyles, CanvasShadowStyles, CanvasFilters, CanvasRect, 
CanvasDrawPath, CanvasUserInterface, CanvasText, CanvasDrawImage, 
CanvasImageData, CanvasPathDrawingStyles, CanvasTextDrawingStyles, CanvasPath {
+  readonly canvas: OffscreenCanvas;
+}
+declare const OffscreenCanvasRenderingContext2D: {
+  prototype: OffscreenCanvasRenderingContext2D;
+  new(): OffscreenCanvasRenderingContext2D;
+}
+
+interface OffscreenCanvas extends EventTarget {
+  width: number;
+  height: number;
+  getContext(contextId: "2d", contextAttributes?: 
CanvasRenderingContext2DSettings): OffscreenCanvasRenderingContext2D | null;
+}
+declare const OffscreenCanvas: {
+  prototype: OffscreenCanvas;
+  new(width: number, height: number): OffscreenCanvas;
+}
+
+function createCanvas(size: number): OffscreenCanvas {
+  if (extensionIsManifestV3()) {
+    return new OffscreenCanvas(size, size)
+  } else {
+    const c = document.createElement("canvas")
+    c.height = size;
+    c.width = size;
+    return c;
+  }
+}
+
+
+async function createImage(size: number, file: string): Promise<ImageData> {
+  const r = await fetch(file)
+  const b = await r.blob()
+  const image = await createImageBitmap(b)
+  const canvas = createCanvas(size);
+  const canvasContext = canvas.getContext('2d')!;
+  canvasContext.clearRect(0, 0, canvas.width, canvas.height);
+  canvasContext.drawImage(image, 0, 0, canvas.width, canvas.height);
+  const imageData = canvasContext.getImageData(0, 0, canvas.width, 
canvas.height);
+  return imageData;
+}
+
+async function registerIconChangeOnTalerContent(): Promise<void> {
+  const imgs = await Promise.all(Object.entries(alertIcons).map(([key, value]) 
=> createImage(parseInt(key, 10), value)))
+  const imageData = imgs.reduce((prev, cur) => ({ ...prev, [cur.width]: cur 
}), {} as { [size: string]: ImageData })
+
+  if (chrome.declarativeContent) {
+    // using declarative content does not need host permission
+    // and is faster
+    const secureTalerUrlLookup = {
+      conditions: [
+        new chrome.declarativeContent.PageStateMatcher({
+          css: ["a[href^='taler://'"]
+        })
+      ],
+      actions: [new chrome.declarativeContent.SetIcon({ imageData })]
+    };
+    const inSecureTalerUrlLookup = {
+      conditions: [
+        new chrome.declarativeContent.PageStateMatcher({
+          css: ["a[href^='taler+http://'"]
+        })
+      ],
+      actions: [new chrome.declarativeContent.SetIcon({ imageData })]
+    };
+    chrome.declarativeContent.onPageChanged.removeRules(undefined, function () 
{
+      chrome.declarativeContent.onPageChanged.addRules([secureTalerUrlLookup, 
inSecureTalerUrlLookup]);
+    });
+    return;
+  }
+
+  //this browser doesn't have declarativeContent
+  //we need host_permission and we will check the content for changing the icon
+  chrome.tabs.onUpdated.addListener(async (tabId, info: 
chrome.tabs.TabChangeInfo) => {
+    if (tabId < 0) return;
+    logger.info("tab updated", tabId, info);
+    if (info.status !== "complete") return;
+    const uri = await findTalerUriInTab(tabId);
+    console.log("urio", uri)
+    if (uri) {
+      setAlertedIcon()
+    } else {
+      setNormalIcon()
+    }
+
+  });
+  chrome.tabs.onActivated.addListener(async ({ tabId }: 
chrome.tabs.TabActiveInfo) => {
+    if (tabId < 0) return;
+    logger.info("tab activated", tabId);
+    const uri = await findTalerUriInTab(tabId);
+    console.log("urio", uri)
+    if (uri) {
+      setAlertedIcon()
+    } else {
+      setNormalIcon()
+    }
+  })
+
+}
+
 function registerOnInstalled(callback: () => void): void {
   // This needs to be outside of main, as Firefox won't fire the event if
   // the listener isn't created synchronously on loading the backend.
-  chrome.runtime.onInstalled.addListener((details) => {
-    console.log(`onInstalled with reason: "${details.reason}"`);
+  chrome.runtime.onInstalled.addListener(async (details) => {
+    logger.info(`onInstalled with reason: "${details.reason}"`);
     if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {
       callback()
     }
+    registerIconChangeOnTalerContent()
   });
 }
 
-function useServiceWorkerAsBackgroundProcess(): boolean {
+function extensionIsManifestV3(): boolean {
   return chrome.runtime.getManifest().manifest_version === 3
 }
 
+function useServiceWorkerAsBackgroundProcess(): boolean {
+  return extensionIsManifestV3()
+}
+
 function searchForTalerLinks(): string | undefined {
   let found;
   found = document.querySelector("a[href^='taler://'")
@@ -382,45 +526,59 @@ function searchForTalerLinks(): string | undefined {
 
 async function getCurrentTab(): Promise<chrome.tabs.Tab> {
   const queryOptions = { active: true, currentWindow: true };
-  const [tab] = await chrome.tabs.query(queryOptions);
-  return tab;
+  return new Promise<chrome.tabs.Tab>((resolve, reject) => {
+    chrome.tabs.query(queryOptions, (tabs) => {
+      if (chrome.runtime.lastError) {
+        reject(chrome.runtime.lastError)
+        return;
+      }
+      resolve(tabs[0])
+    });
+  })
 }
 
-
-async function findTalerUriInActiveTab(): Promise<string | undefined> {
-  if (chrome.runtime.getManifest().manifest_version === 3) {
+async function findTalerUriInTab(tabId: number): Promise<string | undefined> {
+  if (extensionIsManifestV3()) {
     // manifest v3
-    const tab = await getCurrentTab();
-    const res = await chrome.scripting.executeScript({
-      target: {
-        tabId: tab.id!,
-        allFrames: true,
-      } as any,
-      func: searchForTalerLinks,
-      args: []
-    })
-    return res[0].result
+    try {
+      const res = await chrome.scripting.executeScript({
+        target: { tabId, allFrames: true },
+        func: searchForTalerLinks,
+        args: []
+      })
+      return res[0].result
+    } catch (e) {
+      return;
+    }
+  } else {
+    return new Promise((resolve, reject) => {
+      //manifest v2
+      chrome.tabs.executeScript(tabId,
+        {
+          code: `
+            (() => {
+              let x = document.querySelector("a[href^='taler://'") || 
document.querySelector("a[href^='taler+http://'");
+              return x ? x.href.toString() : null;
+            })();
+            `,
+          allFrames: false,
+        },
+        (result) => {
+          if (chrome.runtime.lastError) {
+            console.error(JSON.stringify(chrome.runtime.lastError));
+            resolve(undefined);
+            return;
+          }
+          resolve(result[0]);
+        },
+      );
+    });
   }
-  return new Promise((resolve, reject) => {
-    //manifest v2
-    chrome.tabs.executeScript(
-      {
-        code: `
-        (() => {
-          let x = document.querySelector("a[href^='taler://'") || 
document.querySelector("a[href^='taler+http://'");
-          return x ? x.href.toString() : null;
-        })();
-        `,
-        allFrames: false,
-      },
-      (result) => {
-        if (chrome.runtime.lastError) {
-          console.error(JSON.stringify(chrome.runtime.lastError));
-          resolve(undefined);
-          return;
-        }
-        resolve(result[0]);
-      },
-    );
-  });
 }
+
+async function findTalerUriInActiveTab(): Promise<string | undefined> {
+  const tab = await getCurrentTab();
+  if (!tab || tab.id === undefined) return;
+  return findTalerUriInTab(tab.id)
+}
+

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]