diff --git a/src/background/actions.ts b/src/background/actions.ts index cc1b0e9..946cfd8 100644 --- a/src/background/actions.ts +++ b/src/background/actions.ts @@ -1,5 +1,6 @@ import { Actions, Request } from "../common"; import { sendMessage } from "./messaging"; +import { logger } from "./common"; /** * redirect tab to url. @@ -41,7 +42,7 @@ export function redirectTab(tab: chrome.tabs.Tab, url: string) { * @param {Array} fieldSelectors fields selectors for selecting fields (data columns) under each item * @returns {Promise} a promise of extracted data */ -export function extractTabData(tab, itemsSelector, fieldSelectors) { +export function extractTabData(tab: chrome.tabs.Tab, itemsSelector: string, fieldSelectors: string[], askOnfail?: boolean) { let req = { action: Actions.EXTRACT, itemsSelector: itemsSelector, @@ -49,7 +50,13 @@ export function extractTabData(tab, itemsSelector, fieldSelectors) { } let checker = (result, err, tryCount) => { if (!result || !result.length) { - if (tryCount % 20 == 0 && confirm('No data found in current page. \n\nContinue to next page?')) { + if ( + tryCount % 20 == 0 && ( + !askOnfail || + confirm('No data found in current page. \n\nContinue to next page?') + ) + ) { + logger.warn(`Failed after ${tryCount} tries: ${tab.url}`) return []; } else { return undefined; @@ -135,6 +142,25 @@ export async function findIncognitoWindow(): Promise { }); } +export async function getCurrentWindow(): Promise { + return new Promise((resolve, reject) => { + chrome.windows.getCurrent( + (windows: chrome.windows.Window) => { + return resolve(windows); + } + ); + }); +} + +export async function getWindowByID(id: number) { + return new Promise((resolve, reject) => { + chrome.windows.get(id, function (window) { + chrome.runtime.lastError; + resolve(window); + }) + }) +} + export async function CreateIncognitoWindow() { return new Promise((resolve, reject) => { chrome.windows.create( diff --git a/src/background/messaging.ts b/src/background/messaging.ts index 59ac0ca..dbcb79c 100644 --- a/src/background/messaging.ts +++ b/src/background/messaging.ts @@ -31,7 +31,7 @@ export function sendMessage( loop(); async function loop() { - logger.debug("Request for", req.action); + logger.debug("Request for", Actions[req.action]); let tabAvailable = await getTabByID(tab.id); if (!tabAvailable) { reject("Task interrupted due to the target tab is closed."); diff --git a/src/background/task.ts b/src/background/task.ts index d77a37f..3b8b99d 100644 --- a/src/background/task.ts +++ b/src/background/task.ts @@ -1,5 +1,5 @@ import { parseUrls } from "./tools"; -import { queryUrl, redirectTab, scrollToBottom, extractTabData } from "./actions"; +import { queryUrl, redirectTab, scrollToBottom, extractTabData, findIncognitoWindow, getCurrentWindow, getWindowByID } from "./actions"; import { testArgs, signitures } from "./signiture"; import { ExtractResult } from "./result"; import { messageSubscribers, ActionSubscriber } from "./messaging"; @@ -14,6 +14,7 @@ export class Task { private _fieldSelectors: string[]; private _urls: string[] = []; private _running = false; + private _listeners: ActionSubscriber[] = []; constructor(options: any, ...arg: any); constructor(options: any, itemsSelector: string, fieldSelectors: string[]); @@ -56,15 +57,46 @@ export class Task { } stop() { this._running = false; - messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, this.listener); + let listener: ActionSubscriber; + while (listener = this._listeners.pop()) { + messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, listener); + } } - watch() { + async watch() { if (this._running) { logger.info("The task is running. Please wait..."); return; } this._running = true; - messageSubscribers.addListener(Actions.REPORT_NEW_PAGE, this.listener); + let window = await findIncognitoWindow() || await getCurrentWindow(); + if (!window) { + logger.info("No window to watch..."); + return; + } + let listener: ActionSubscriber = async (request, sender, sendResponse) => { + let findWindow = await getWindowByID(window.id); + if (!findWindow) { + // stop watch on window close. + messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, listener); + return; + } + // only watch current window. + if (sender.tab.windowId != window.id) return; + let pm = this.makeOptionalTasks(sender.tab); + return pm.then( + () => extractTabData(sender.tab, this._itemsSelector, this._fieldSelectors, false) + ).then( + results => { + if (results && results.length) { + this.saveResult(results, sender.tab.url); + } + } + ).catch( + e => logger.error(e) + ) + } + this._listeners.push(listener); + messageSubscribers.addListener(Actions.REPORT_NEW_PAGE, listener); } async execute(tab: chrome.tabs.Tab, upstreamData?: ExtractResult): Promise { if (!tab) return Promise.reject("No tab to execute the task."); @@ -108,21 +140,6 @@ export class Task { } ); } - private listener: ActionSubscriber = (request, sender, sendResponse) => { - sendResponse('recieved!'); - let pm = this.makeOptionalTasks(sender.tab); - return pm.then( - () => extractTabData(sender.tab, this._itemsSelector, this._fieldSelectors) - ).then( - results => { - if (results && results.length) { - this.saveResult(results, sender.tab.url); - } - } - ).catch( - e => logger.error(e) - ) - } private makeOptionalTasks(tab: chrome.tabs.Tab): Promise { let pm: Promise; if (this._options["scrollToBottom"]) {