Kaynağa Gözat

fix: javascript block not working in firefox

Ahmad Kholid 2 yıl önce
ebeveyn
işleme
280c7f51b9

+ 3 - 1
src/background/index.js

@@ -12,7 +12,9 @@ browser.alarms.onAlarm.addListener(BackgroundEventsListeners.onAlarms);
 
 browser.commands.onCommand.addListener(BackgroundEventsListeners.onCommand);
 
-browser.action.onClicked.addListener(BackgroundEventsListeners.onActionClicked);
+(browser.action || browser.browserAction).onClicked.addListener(
+  BackgroundEventsListeners.onActionClicked
+);
 
 browser.runtime.onStartup.addListener(
   BackgroundEventsListeners.onRuntimeStartup

+ 6 - 2
src/components/newtab/workflow/edit/EditJavascriptCode.vue

@@ -17,6 +17,7 @@
         @change="updateData({ timeout: +$event })"
       />
       <ui-select
+        v-if="!isFirefox"
         :model-value="data.context"
         :label="t('workflow.blocks.javascript-code.context.name')"
         class="mb-2 w-full"
@@ -40,7 +41,7 @@
       @click="state.showCodeModal = true"
       v-text="data.code"
     />
-    <template v-if="data.context !== 'background'">
+    <template v-if="isFirefox || data.context !== 'background'">
       <ui-checkbox
         :model-value="data.everyNewTab"
         class="mt-2"
@@ -127,7 +128,9 @@
               class="flex-1 mr-4"
             />
             <ui-checkbox
-              v-if="!data.everyNewTab || data.context !== 'website'"
+              v-if="
+                (!data.everyNewTab || data.context !== 'website') && !isFirefox
+              "
               v-model="state.preloadScripts[index].removeAfterExec"
             >
               {{ t('workflow.blocks.javascript-code.removeAfterExec') }}
@@ -174,6 +177,7 @@ const emit = defineEmits(['update:data']);
 
 const { t } = useI18n();
 
+const isFirefox = BROWSER_TYPE === 'firefox';
 const availableFuncs = [
   { name: 'automaNextBlock(data, insert?)', id: 'automanextblock-data' },
   { name: 'automaRefData(keyword, path?)', id: 'automarefdata-keyword-path' },

+ 7 - 0
src/content/blocksHandler/handlerJavascriptCode.js

@@ -0,0 +1,7 @@
+import { jsContentHandler } from '@/newtab/utils/javascriptBlockUtil';
+
+function javascriptCode({ data }) {
+  return jsContentHandler(...data);
+}
+
+export default javascriptCode;

+ 2 - 5
src/manifest.firefox.json

@@ -10,10 +10,7 @@
     "scripts": ["background.bundle.js"],
     "persistent": false
   },
-  "browser_action": {
-    "default_popup": "popup.html",
-    "default_icon": "icon-128.png"
-  },
+  "browser_action": {},
   "icons": {
     "128": "icon-128.png"
   },
@@ -58,5 +55,5 @@
     "/locales/*",
     "elementSelector.bundle.js"
   ],
-  "content_security_policy": "script-src 'self' https:; object-src 'self'"
+  "content_security_policy": "script-src 'self' 'unsafe-inline' https:; object-src 'self'"
 }

+ 121 - 0
src/newtab/utils/javascriptBlockUtil.js

@@ -0,0 +1,121 @@
+export function jsContentHandler($blockData, $preloadScripts, $automaScript) {
+  return new Promise((resolve, reject) => {
+    try {
+      let $documentCtx = document;
+
+      if ($blockData.frameSelector) {
+        const iframeCtx = document.querySelector(
+          $blockData.frameSelector
+        )?.contentDocument;
+
+        if (!iframeCtx) {
+          reject(new Error('iframe-not-found'));
+          return;
+        }
+
+        $documentCtx = iframeCtx;
+      }
+
+      const scriptAttr = `block--${$blockData.id}`;
+
+      const isScriptExists = $documentCtx.querySelector(
+        `.automa-custom-js[${scriptAttr}]`
+      );
+      if (isScriptExists) {
+        resolve('');
+        return;
+      }
+
+      const script = document.createElement('script');
+      script.setAttribute(scriptAttr, '');
+      script.classList.add('automa-custom-js');
+      script.textContent = `(() => {
+        ${$automaScript}
+
+        try {
+          ${$blockData.data.code}
+          ${
+            $blockData.data.everyNewTab ||
+            $blockData.data.code.includes('automaNextBlock')
+              ? ''
+              : 'automaNextBlock()'
+          }
+        } catch (error) {
+          console.error(error);
+          ${
+            $blockData.data.everyNewTab
+              ? ''
+              : 'automaNextBlock({ $error: true, message: error.message })'
+          }
+        }
+      })()`;
+
+      const preloadScriptsEl = $preloadScripts.map((item) => {
+        const scriptEl = document.createElement('script');
+        scriptEl.id = item.id;
+        scriptEl.textContent = item.script;
+
+        $documentCtx.head.appendChild(scriptEl);
+
+        return { element: scriptEl, removeAfterExec: item.removeAfterExec };
+      });
+
+      if (!$blockData.data.everyNewTab) {
+        let timeout;
+        let onNextBlock;
+        let onResetTimeout;
+
+        /* eslint-disable-next-line */
+        function cleanUp() {
+          script.remove();
+          preloadScriptsEl.forEach((item) => {
+            if (item.removeAfterExec) item.script.remove();
+          });
+
+          clearTimeout(timeout);
+
+          $documentCtx.body.removeEventListener(
+            '__automa-reset-timeout__',
+            onResetTimeout
+          );
+          $documentCtx.body.removeEventListener(
+            '__automa-next-block__',
+            onNextBlock
+          );
+        }
+
+        onNextBlock = ({ detail }) => {
+          cleanUp(detail || {});
+          resolve({
+            columns: {
+              data: detail?.data,
+              insert: detail?.insert,
+            },
+            variables: detail?.refData?.variables,
+          });
+        };
+        onResetTimeout = () => {
+          clearTimeout(timeout);
+          timeout = setTimeout(cleanUp, $blockData.data.timeout);
+        };
+
+        $documentCtx.body.addEventListener(
+          '__automa-next-block__',
+          onNextBlock
+        );
+        $documentCtx.body.addEventListener(
+          '__automa-reset-timeout__',
+          onResetTimeout
+        );
+
+        timeout = setTimeout(cleanUp, $blockData.data.timeout);
+      } else {
+        resolve();
+      }
+
+      $documentCtx.head.appendChild(script);
+    } catch (error) {
+      console.error(error);
+    }
+  });
+}

+ 1 - 0
src/newtab/workflowEngine/WorkflowEngine.js

@@ -16,6 +16,7 @@ class WorkflowEngine {
     this.blocksHandler = blocksHandler;
     this.parentWorkflow = options?.parentWorkflow;
     this.saveLog = workflow.settings?.saveLog ?? true;
+    this.isMV2 = browser.runtime.getManifest().manifest_version === 2;
 
     this.workerId = 0;
     this.workers = new Map();

+ 22 - 126
src/newtab/workflowEngine/blocksHandler/handlerJavascriptCode.js

@@ -1,6 +1,7 @@
 import { customAlphabet } from 'nanoid/non-secure';
 import browser from 'webextension-polyfill';
 import cloneDeep from 'lodash.clonedeep';
+import { jsContentHandler } from '@/newtab/utils/javascriptBlockUtil';
 import { messageSandbox, automaRefDataStr, waitTabLoaded } from '../helper';
 
 const nanoid = customAlphabet('1234567890abcdef', 5);
@@ -26,132 +27,23 @@ function automaResetTimeout() {
 
   return str;
 }
-async function executeInWebpage(args, target) {
+async function executeInWebpage(args, target, worker) {
+  if (worker.engine.isMV2 || BROWSER_TYPE === 'firefox') {
+    args[0] = cloneDeep(args[0]);
+
+    const result = await worker._sendMessageToTab({
+      label: 'javascript-code',
+      data: args,
+    });
+
+    return result;
+  }
+
   const [{ result }] = await browser.scripting.executeScript({
     args,
     target,
     world: 'MAIN',
-    func: ($blockData, $preloadScripts, $automaScript) => {
-      return new Promise((resolve, reject) => {
-        try {
-          let $documentCtx = document;
-
-          if ($blockData.frameSelector) {
-            const iframeCtx = document.querySelector(
-              $blockData.frameSelector
-            )?.contentDocument;
-
-            if (!iframeCtx) {
-              reject(new Error('iframe-not-found'));
-              return;
-            }
-
-            $documentCtx = iframeCtx;
-          }
-
-          const scriptAttr = `block--${$blockData.id}`;
-
-          const isScriptExists = $documentCtx.querySelector(
-            `.automa-custom-js[${scriptAttr}]`
-          );
-          if (isScriptExists) {
-            resolve('');
-            return;
-          }
-
-          const script = document.createElement('script');
-          script.setAttribute(scriptAttr, '');
-          script.classList.add('automa-custom-js');
-          script.textContent = `(() => {
-            ${$automaScript}
-
-            try {
-              ${$blockData.data.code}
-              ${
-                $blockData.data.everyNewTab ||
-                $blockData.data.code.includes('automaNextBlock')
-                  ? ''
-                  : 'automaNextBlock()'
-              }
-            } catch (error) {
-              console.error(error);
-              ${
-                $blockData.data.everyNewTab
-                  ? ''
-                  : 'automaNextBlock({ $error: true, message: error.message })'
-              }
-            }
-          })()`;
-
-          const preloadScriptsEl = $preloadScripts.map((item) => {
-            const scriptEl = document.createElement('script');
-            scriptEl.id = item.id;
-            scriptEl.textContent = item.script;
-
-            $documentCtx.head.appendChild(scriptEl);
-
-            return { element: scriptEl, removeAfterExec: item.removeAfterExec };
-          });
-
-          if (!$blockData.data.everyNewTab) {
-            let timeout;
-            let onNextBlock;
-            let onResetTimeout;
-
-            /* eslint-disable-next-line */
-            function cleanUp() {
-              script.remove();
-              preloadScriptsEl.forEach((item) => {
-                if (item.removeAfterExec) item.script.remove();
-              });
-
-              clearTimeout(timeout);
-
-              $documentCtx.body.removeEventListener(
-                '__automa-reset-timeout__',
-                onResetTimeout
-              );
-              $documentCtx.body.removeEventListener(
-                '__automa-next-block__',
-                onNextBlock
-              );
-            }
-
-            onNextBlock = ({ detail }) => {
-              cleanUp(detail || {});
-              resolve({
-                columns: {
-                  data: detail?.data,
-                  insert: detail?.insert,
-                },
-                variables: detail?.refData?.variables,
-              });
-            };
-            onResetTimeout = () => {
-              clearTimeout(timeout);
-              timeout = setTimeout(cleanUp, $blockData.data.timeout);
-            };
-
-            $documentCtx.body.addEventListener(
-              '__automa-next-block__',
-              onNextBlock
-            );
-            $documentCtx.body.addEventListener(
-              '__automa-reset-timeout__',
-              onResetTimeout
-            );
-
-            timeout = setTimeout(cleanUp, $blockData.data.timeout);
-          } else {
-            resolve();
-          }
-
-          $documentCtx.head.appendChild(script);
-        } catch (error) {
-          console.error(error);
-        }
-      });
-    },
+    func: jsContentHandler,
   });
 
   return result;
@@ -220,10 +112,14 @@ export async function javascriptCode({ outputs, data, ...block }, { refData }) {
         refData: payload.refData,
         blockData: cloneDeep(payload.data),
       })
-    : executeInWebpage([payload, preloadScripts, automaScript], {
-        tabId: this.activeTab.id,
-        frameIds: [this.activeTab.frameId || 0],
-      }));
+    : executeInWebpage(
+        [payload, preloadScripts, automaScript],
+        {
+          tabId: this.activeTab.id,
+          frameIds: [this.activeTab.frameId || 0],
+        },
+        this
+      ));
 
   if (result) {
     if (result.columns.data?.$error) {