|
@@ -0,0 +1,132 @@
|
|
|
+import browser from 'webextension-polyfill';
|
|
|
+import { getBlockConnection } from '../helper';
|
|
|
+import { isWhitespace } from '@/utils/helper';
|
|
|
+
|
|
|
+function handleEventListener(target, validate) {
|
|
|
+ return (data, activeTab) => {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ let resolved = false;
|
|
|
+ const eventListener = (event) => {
|
|
|
+ if (resolved) return;
|
|
|
+ if (validate && !validate(event, { data, activeTab })) return;
|
|
|
+
|
|
|
+ target.removeListener(eventListener);
|
|
|
+ resolve(event);
|
|
|
+ };
|
|
|
+
|
|
|
+ setTimeout(() => {
|
|
|
+ resolved = true;
|
|
|
+ target.removeListener(eventListener);
|
|
|
+ resolve('');
|
|
|
+ }, data.timeout || 10000);
|
|
|
+
|
|
|
+ target.addListener(eventListener);
|
|
|
+ });
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+function onTabLoaded({ tabLoadedUrl, activeTabLoaded, timeout }, { id }) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ let resolved = false;
|
|
|
+
|
|
|
+ const checkActiveTabStatus = () => {
|
|
|
+ if (resolved) return;
|
|
|
+ if (!id) {
|
|
|
+ reject(new Error('no-tab'));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ browser.tabs
|
|
|
+ .get(id)
|
|
|
+ .then((tab) => {
|
|
|
+ if (tab.status === 'complete') {
|
|
|
+ resolve();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ setTimeout(checkActiveTabStatus, 1000);
|
|
|
+ })
|
|
|
+ .catch(reject);
|
|
|
+ };
|
|
|
+
|
|
|
+ const url = isWhitespace(tabLoadedUrl)
|
|
|
+ ? '<all_urls>'
|
|
|
+ : tabLoadedUrl.replace(/\s/g, '').split(',');
|
|
|
+ const checkTabsStatus = () => {
|
|
|
+ browser.tabs
|
|
|
+ .query({
|
|
|
+ url,
|
|
|
+ status: 'loading',
|
|
|
+ })
|
|
|
+ .then((tabs) => {
|
|
|
+ if (resolved) return;
|
|
|
+ if (tabs.length === 0) {
|
|
|
+ resolve();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ setTimeout(checkTabsStatus, 1000);
|
|
|
+ })
|
|
|
+ .catch(reject);
|
|
|
+ };
|
|
|
+
|
|
|
+ if (activeTabLoaded) checkActiveTabStatus();
|
|
|
+ else checkTabsStatus();
|
|
|
+
|
|
|
+ setTimeout(() => {
|
|
|
+ resolved = true;
|
|
|
+ resolve('');
|
|
|
+ }, timeout || 10000);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const validateCreatedTab = ({ url }, { data }) => {
|
|
|
+ if (!isWhitespace(data.tabUrl)) {
|
|
|
+ const regex = new RegExp(data.tabUrl, 'gi');
|
|
|
+
|
|
|
+ if (!regex.test(url)) return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+};
|
|
|
+const events = {
|
|
|
+ 'tab:loaded': onTabLoaded,
|
|
|
+ 'tab:close': handleEventListener(browser.tabs.onRemoved),
|
|
|
+ 'tab:create': handleEventListener(
|
|
|
+ browser.webNavigation.onCreatedNavigationTarget,
|
|
|
+ validateCreatedTab
|
|
|
+ ),
|
|
|
+ 'window:create': handleEventListener(
|
|
|
+ browser.webNavigation.onCreatedNavigationTarget,
|
|
|
+ validateCreatedTab
|
|
|
+ ),
|
|
|
+ 'window:close': handleEventListener(browser.windows.onRemoved),
|
|
|
+};
|
|
|
+
|
|
|
+export default async function ({ data, outputs }) {
|
|
|
+ const nextBlockId = getBlockConnection({ outputs });
|
|
|
+
|
|
|
+ try {
|
|
|
+ const currentEvent = events[data.eventName];
|
|
|
+
|
|
|
+ if (!currentEvent) {
|
|
|
+ throw new Error(`Can't find ${data.eventName} event`);
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = await currentEvent(data, this.activeTab);
|
|
|
+
|
|
|
+ if (data.eventName === 'tab:create' && data.setAsActiveTab) {
|
|
|
+ this.activeTab.id = result.tabId;
|
|
|
+ this.activeTab.url = result.url;
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ nextBlockId,
|
|
|
+ data: result || '',
|
|
|
+ };
|
|
|
+ } catch (error) {
|
|
|
+ error.nextBlockId = nextBlockId;
|
|
|
+
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+}
|