|
@@ -1,5 +1,6 @@
|
|
|
import { customAlphabet } from 'nanoid/non-secure';
|
|
|
import browser from 'webextension-polyfill';
|
|
|
+import cloneDeep from 'lodash.clonedeep';
|
|
|
import { automaRefDataStr, waitTabLoaded } from '../helper';
|
|
|
|
|
|
const nanoid = customAlphabet('1234567890abcdef', 5);
|
|
@@ -25,68 +26,28 @@ function automaResetTimeout() {
|
|
|
|
|
|
return str;
|
|
|
}
|
|
|
+function executeInSandbox(data) {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ const messageId = nanoid();
|
|
|
|
|
|
-export async function javascriptCode({ outputs, data, ...block }, { refData }) {
|
|
|
- const nextBlockId = this.getBlockConnections(block.id);
|
|
|
-
|
|
|
- if (data.everyNewTab) {
|
|
|
- const isScriptExist = this.preloadScripts.some(({ id }) => id === block.id);
|
|
|
- if (!isScriptExist) this.preloadScripts.push({ ...block, data });
|
|
|
- if (!this.activeTab.id) return { data: '', nextBlockId };
|
|
|
- } else if (!this.activeTab.id) {
|
|
|
- throw new Error('no-tab');
|
|
|
- }
|
|
|
-
|
|
|
- const payload = {
|
|
|
- ...block,
|
|
|
- data,
|
|
|
- refData: { variables: {} },
|
|
|
- frameSelector: this.frameSelector,
|
|
|
- };
|
|
|
- if (data.code.includes('automaRefData')) {
|
|
|
- payload.refData = { ...refData, secrets: {} };
|
|
|
- }
|
|
|
-
|
|
|
- const preloadScriptsPromise = await Promise.allSettled(
|
|
|
- data.preloadScripts.map(async (script) => {
|
|
|
- const { protocol } = new URL(script.src);
|
|
|
- const isValidUrl = /https?/.test(protocol);
|
|
|
- if (!isValidUrl) return null;
|
|
|
-
|
|
|
- const response = await fetch(script.src);
|
|
|
- if (!response.ok) throw new Error(response.statusText);
|
|
|
-
|
|
|
- const result = await response.text();
|
|
|
-
|
|
|
- return {
|
|
|
- script: result,
|
|
|
- id: `automa-script-${nanoid()}`,
|
|
|
- removeAfterExec: script.removeAfterExec,
|
|
|
- };
|
|
|
- })
|
|
|
- );
|
|
|
- const preloadScripts = preloadScriptsPromise.reduce((acc, item) => {
|
|
|
- if (item.status === 'fulfilled') acc.push(item.value);
|
|
|
+ const iframeEl = document.querySelector('#sandbox');
|
|
|
+ iframeEl.contentWindow.postMessage({ id: messageId, ...data }, '*');
|
|
|
|
|
|
- return acc;
|
|
|
- }, []);
|
|
|
+ const messageListener = ({ data: messageData }) => {
|
|
|
+ if (messageData?.type !== 'sandbox' || messageData?.id !== messageId)
|
|
|
+ return;
|
|
|
|
|
|
- const automaScript = data.everyNewTab
|
|
|
- ? ''
|
|
|
- : getAutomaScript(payload.refData, data.everyNewTab);
|
|
|
+ resolve(messageData.result);
|
|
|
+ };
|
|
|
|
|
|
- await waitTabLoaded({
|
|
|
- tabId: this.activeTab.id,
|
|
|
- ms: this.settings?.tabLoadTimeout ?? 30000,
|
|
|
+ window.addEventListener('message', messageListener, { once: true });
|
|
|
});
|
|
|
-
|
|
|
+}
|
|
|
+async function executeInWebpage(args, target) {
|
|
|
const [{ result }] = await browser.scripting.executeScript({
|
|
|
+ args,
|
|
|
+ target,
|
|
|
world: 'MAIN',
|
|
|
- args: [payload, preloadScripts, automaScript],
|
|
|
- target: {
|
|
|
- tabId: this.activeTab.id,
|
|
|
- frameIds: [this.activeTab.frameId || 0],
|
|
|
- },
|
|
|
func: ($blockData, $preloadScripts, $automaScript) => {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
try {
|
|
@@ -155,7 +116,7 @@ export async function javascriptCode({ outputs, data, ...block }, { refData }) {
|
|
|
let onResetTimeout;
|
|
|
|
|
|
/* eslint-disable-next-line */
|
|
|
- function cleanUp(detail) {
|
|
|
+ function cleanUp() {
|
|
|
script.remove();
|
|
|
preloadScriptsEl.forEach((item) => {
|
|
|
if (item.removeAfterExec) item.script.remove();
|
|
@@ -171,7 +132,10 @@ export async function javascriptCode({ outputs, data, ...block }, { refData }) {
|
|
|
'__automa-next-block__',
|
|
|
onNextBlock
|
|
|
);
|
|
|
+ }
|
|
|
|
|
|
+ onNextBlock = ({ detail }) => {
|
|
|
+ cleanUp(detail || {});
|
|
|
resolve({
|
|
|
columns: {
|
|
|
data: detail?.data,
|
|
@@ -179,10 +143,6 @@ export async function javascriptCode({ outputs, data, ...block }, { refData }) {
|
|
|
},
|
|
|
variables: detail?.refData?.variables,
|
|
|
});
|
|
|
- }
|
|
|
-
|
|
|
- onNextBlock = ({ detail }) => {
|
|
|
- cleanUp(detail || {});
|
|
|
};
|
|
|
onResetTimeout = () => {
|
|
|
clearTimeout(timeout);
|
|
@@ -211,6 +171,77 @@ export async function javascriptCode({ outputs, data, ...block }, { refData }) {
|
|
|
},
|
|
|
});
|
|
|
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+export async function javascriptCode({ outputs, data, ...block }, { refData }) {
|
|
|
+ const nextBlockId = this.getBlockConnections(block.id);
|
|
|
+
|
|
|
+ if (data.everyNewTab) {
|
|
|
+ const isScriptExist = this.preloadScripts.some(({ id }) => id === block.id);
|
|
|
+ if (!isScriptExist) this.preloadScripts.push({ ...block, data });
|
|
|
+ if (!this.activeTab.id) return { data: '', nextBlockId };
|
|
|
+ } else if (!this.activeTab.id && data.context !== 'background') {
|
|
|
+ throw new Error('no-tab');
|
|
|
+ }
|
|
|
+
|
|
|
+ const payload = {
|
|
|
+ ...block,
|
|
|
+ data,
|
|
|
+ refData: { variables: {} },
|
|
|
+ frameSelector: this.frameSelector,
|
|
|
+ };
|
|
|
+ if (data.code.includes('automaRefData')) {
|
|
|
+ payload.refData = { ...refData, secrets: {} };
|
|
|
+ }
|
|
|
+
|
|
|
+ const preloadScriptsPromise = await Promise.allSettled(
|
|
|
+ data.preloadScripts.map(async (script) => {
|
|
|
+ const { protocol } = new URL(script.src);
|
|
|
+ const isValidUrl = /https?/.test(protocol);
|
|
|
+ if (!isValidUrl) return null;
|
|
|
+
|
|
|
+ const response = await fetch(script.src);
|
|
|
+ if (!response.ok) throw new Error(response.statusText);
|
|
|
+
|
|
|
+ const result = await response.text();
|
|
|
+
|
|
|
+ return {
|
|
|
+ script: result,
|
|
|
+ id: `automa-script-${nanoid()}`,
|
|
|
+ removeAfterExec: script.removeAfterExec,
|
|
|
+ };
|
|
|
+ })
|
|
|
+ );
|
|
|
+ const preloadScripts = preloadScriptsPromise.reduce((acc, item) => {
|
|
|
+ if (item.status === 'fulfilled') acc.push(item.value);
|
|
|
+
|
|
|
+ return acc;
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ const automaScript =
|
|
|
+ data.everyNewTab || data.context === 'background'
|
|
|
+ ? ''
|
|
|
+ : getAutomaScript(payload.refData, data.everyNewTab);
|
|
|
+
|
|
|
+ if (data.context !== 'background') {
|
|
|
+ await waitTabLoaded({
|
|
|
+ tabId: this.activeTab.id,
|
|
|
+ ms: this.settings?.tabLoadTimeout ?? 30000,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = await (data.context === 'background'
|
|
|
+ ? executeInSandbox({
|
|
|
+ preloadScripts,
|
|
|
+ refData: payload.refData,
|
|
|
+ blockData: cloneDeep(payload.data),
|
|
|
+ })
|
|
|
+ : executeInWebpage([payload, preloadScripts, automaScript], {
|
|
|
+ tabId: this.activeTab.id,
|
|
|
+ frameIds: [this.activeTab.frameId || 0],
|
|
|
+ }));
|
|
|
+
|
|
|
if (result) {
|
|
|
if (result.columns.data?.$error) {
|
|
|
throw new Error(result.columns.data.message);
|