瀏覽代碼

fix: `automaFetch` not working in the background context

Ahmad Kholid 2 年之前
父節點
當前提交
f14234d991

+ 3 - 1
src/content/index.js

@@ -248,7 +248,9 @@ window.addEventListener('__automa-fetch__', (event) => {
   const { id, resource, type } = event.detail;
   const sendResponse = (payload) => {
     window.dispatchEvent(
-      new CustomEvent(`__autom-fetch-response-${id}__`, { detail: payload })
+      new CustomEvent(`__autom-fetch-response-${id}__`, {
+        detail: { id, ...payload },
+      })
     );
   };
 

+ 24 - 0
src/newtab/App.vue

@@ -74,6 +74,7 @@ import { useSharedWorkflowStore } from '@/stores/sharedWorkflow';
 import { loadLocaleMessages, setI18nLanguage } from '@/lib/vueI18n';
 import { getUserWorkflows } from '@/utils/api';
 import { getWorkflowPermissions } from '@/utils/workflowData';
+import { sendMessage } from '@/utils/message';
 import automa from '@business';
 import dbLogs from '@/db/logs';
 import dayjs from '@/lib/dayjs';
@@ -252,6 +253,29 @@ window.onbeforeunload = () => {
     return t('message.notSaved');
   }
 };
+window.addEventListener('message', ({ data }) => {
+  if (data?.type !== 'automa-fetch') return;
+
+  const sendResponse = (result) => {
+    const sandbox = document.getElementById('sandbox');
+    sandbox.contentWindow.postMessage(
+      {
+        type: 'fetchResponse',
+        data: result,
+        id: data.data.id,
+      },
+      '*'
+    );
+  };
+
+  sendMessage('fetch', data.data, 'background')
+    .then((result) => {
+      sendResponse({ isError: false, result });
+    })
+    .catch((error) => {
+      sendResponse({ isError: true, result: error.message });
+    });
+});
 
 (async () => {
   try {

+ 4 - 2
src/newtab/utils/javascriptBlockUtil.js

@@ -8,7 +8,9 @@ export function automaFetchClient(id, { type, resource }) {
 
     const eventName = `__autom-fetch-response-${id}__`;
     const eventListener = ({ detail }) => {
-      window.removeEventListener(eventName, eventListener, { once: true });
+      if (detail.id !== id) return;
+
+      window.removeEventListener(eventName, eventListener);
 
       if (detail.isError) {
         reject(new Error(detail.result));
@@ -17,7 +19,7 @@ export function automaFetchClient(id, { type, resource }) {
       }
     };
 
-    window.addEventListener(eventName, eventListener, { once: true });
+    window.addEventListener(eventName, eventListener);
     window.dispatchEvent(
       new CustomEvent(`__automa-fetch__`, {
         detail: {

+ 2 - 1
src/newtab/workflowEngine/blocksHandler/handlerJavascriptCode.js

@@ -113,7 +113,8 @@ export async function javascriptCode({ outputs, data, ...block }, { refData }) {
     });
   }
 
-  const result = await (data.context === 'background'
+  const inSandbox = BROWSER_TYPE !== 'firefox' && data.context === 'background';
+  const result = await (inSandbox
     ? messageSandbox('javascriptBlock', {
         instanceId,
         preloadScripts,

+ 3 - 1
src/newtab/workflowEngine/helper.js

@@ -14,10 +14,12 @@ export function messageSandbox(type, data = {}) {
       if (messageData?.type !== 'sandbox' || messageData?.id !== messageId)
         return;
 
+      window.removeEventListener('message', messageListener);
+
       resolve(messageData.result);
     };
 
-    window.addEventListener('message', messageListener, { once: true });
+    window.addEventListener('message', messageListener);
   });
 }
 

+ 9 - 0
src/sandbox/index.js

@@ -5,7 +5,16 @@ import handleBlockExpression from './utils/handleBlockExpression';
 
 window.$getNestedProperties = objectPath.get;
 
+function fetchResponse({ id, data }) {
+  window.dispatchEvent(
+    new CustomEvent(`automa-fetch-response-${id}`, {
+      detail: data,
+    })
+  );
+}
+
 const eventHandlers = {
+  fetchResponse,
   conditionCode: handleConditionCode,
   blockExpression: handleBlockExpression,
   javascriptBlock: handleJavascriptBlock,

+ 37 - 0
src/sandbox/utils/handleJavascriptBlock.js

@@ -1,5 +1,8 @@
+import { nanoid } from 'nanoid/non-secure';
+
 export default function (data) {
   let timeout;
+  const instanceId = nanoid();
   const scriptId = `script${data.id}`;
   const propertyName = `automa${data.id}`;
 
@@ -49,6 +52,9 @@ export default function (data) {
       function automaResetTimeout() {
         ${propertyName}.resetTimeout();
       }
+      function automaFetch(type, resource) {
+        return ${propertyName}.fetch(type, resource);
+      }
 
       try {
         ${data.blockData.code}
@@ -91,6 +97,37 @@ export default function (data) {
       clearTimeout(timeout);
       timeout = setTimeout(cleanUp, data.blockData.timeout);
     },
+    fetch: (type, resource) => {
+      return new Promise((resolve, reject) => {
+        const types = ['json', 'text'];
+        if (!type || !types.includes(type)) {
+          reject(new Error('The "type" must be "text" or "json"'));
+          return;
+        }
+
+        window.top.postMessage(
+          {
+            type: 'automa-fetch',
+            data: { id: instanceId, type, resource },
+          },
+          '*'
+        );
+
+        const eventName = `automa-fetch-response-${instanceId}`;
+
+        const eventListener = ({ detail }) => {
+          window.removeEventListener(eventName, eventListener);
+
+          if (detail.isError) {
+            reject(new Error(detail.result));
+          } else {
+            resolve(detail.result);
+          }
+        };
+
+        window.addEventListener(eventName, eventListener);
+      });
+    },
   };
 
   timeout = setTimeout(cleanUp, data.blockData.timeout);