Gtranslate queue

This commit is contained in:
a 2020-08-12 00:20:46 +02:00
parent d5092e4ac0
commit 57ec8ac956
2 changed files with 53 additions and 18 deletions

View file

@ -7,7 +7,8 @@ import content_script from "../frontend/content_script/content_script.ts?file";
let com = new Communicator(); let com = new Communicator();
const scraper = new GTranslateScraper(); const scraper = new GTranslateScraper();
com.translateCallback = (toTranslate) => scraper.translate(toTranslate); com.translateCallback = (toTranslate, sender) =>
scraper.translate(toTranslate, sender.tab?.id);
const db = new Flashcards(); const db = new Flashcards();
com.addFlashcardCallback = (c) => db.addFlashcard(c); com.addFlashcardCallback = (c) => db.addFlashcard(c);

View file

@ -1,23 +1,29 @@
import { browser, WebRequest, Runtime } from "webextension-polyfill-ts"; import { browser, WebRequest, Runtime } from "webextension-polyfill-ts";
import content_script from "./gtranslate_content_script.ts?file"; import content_script from "./gtranslate_content_script.ts?file";
interface TranslationRequest {
tabID?: number;
resolveFn: (value: Translation) => void;
rejectFn: (reason: String) => void;
toTranslate: string;
}
export class GTranslateScraper { export class GTranslateScraper {
iframe: HTMLIFrameElement; private conn?: Runtime.Port;
conn?: Runtime.Port; private current?: TranslationRequest;
resolveFn?: (value: Translation) => void; private queue: Array<TranslationRequest> = [];
rejectFn?: (reason: String) => void;
constructor() { constructor() {
browser.runtime.onConnect.addListener((p) => { browser.runtime.onConnect.addListener((p) => {
if (p.name != "gtranslate_scraper_conn") return; if (p.name != "gtranslate_scraper_conn") return;
this.conn = p; this.conn = p;
this.processFromQueue(p);
p.onMessage.addListener((m) => this.onTranslationRecieved(m)); p.onMessage.addListener((m) => this.onTranslationRecieved(m));
}); });
//This allows us to create the google translate iframe by removing the x-frame-options header //This allows us to create the google translate iframe by removing the x-frame-options header
browser.webRequest.onHeadersReceived.addListener( browser.webRequest.onHeadersReceived.addListener(
allowIFrameAccess, allowIFrameAccess,
{ {
urls: ["<all_urls>"], urls: ["<all_urls>"],
types: ["sub_frame"], types: ["sub_frame"],
@ -28,7 +34,6 @@ export class GTranslateScraper {
//TODO make the language customizable //TODO make the language customizable
iframe.src = "https://translate.google.com/?op=translate&sl=de&tl=en"; iframe.src = "https://translate.google.com/?op=translate&sl=de&tl=en";
this.iframe = iframe;
//Registers a temp content script, because we cannot inject scripts into iframes created on the background html page, because they have no tabId //Registers a temp content script, because we cannot inject scripts into iframes created on the background html page, because they have no tabId
const js = { const js = {
@ -46,21 +51,50 @@ export class GTranslateScraper {
document.body.appendChild(iframe); document.body.appendChild(iframe);
}); });
} }
onTranslationRecieved(message: Translation) { private onTranslationRecieved(message: Translation) {
if (this.resolveFn) this.resolveFn(message); if (this.current) this.current.resolveFn(message);
this.resolveFn = undefined; this.current = undefined;
this.rejectFn = undefined; this.processFromQueue(this.conn!);
} }
translate(to_translate: string): Promise<Translation> { private processTranslationRequest(
if (this.rejectFn) this.rejectFn("Got a different translation request"); request: TranslationRequest,
if (!this.conn) return Promise.reject("The translator is not yet ready"); conn: Runtime.Port
) {
this.current = request;
conn.postMessage(request.toTranslate);
}
this.conn.postMessage(to_translate); private processFromQueue(conn: Runtime.Port) {
return new Promise((resolve, reject) => { const next = this.queue.pop();
this.resolveFn = resolve; if (next) this.processTranslationRequest(next, conn);
this.rejectFn = reject; }
translate(to_translate: string, tabID?: number): Promise<Translation> {
if (to_translate == "") return Promise.resolve({ src: "", result: "" });
const p = new Promise((resolve: (value: Translation) => void, reject) => {
const req = {
toTranslate: to_translate,
resolveFn: resolve,
rejectFn: reject,
tabID: tabID,
};
if (this.current || !this.conn) {
//Remove the requests from the same tab
if (tabID)
this.queue = this.queue.filter((r) => {
if (r.tabID !== tabID) {
r.rejectFn("Got another request from the same tab");
return true;
}
}); });
this.queue.push(req);
} else {
this.processTranslationRequest(req, this.conn);
}
});
return p;
} }
} }