From cb12a65a8f8e3b97e9c6ca79881be416fb51ecd4 Mon Sep 17 00:00:00 2001 From: coomdev Date: Mon, 18 Jul 2022 20:57:26 +0200 Subject: [PATCH] Transfer files between iframe more efficiently on chrome and works on brave --- chrome/dist/background.js | 20 ++++--- chrome/dist/main.js | 120 +++++++++++++++----------------------- chrome/manifest.json | 2 +- src/background.ts | 51 +++++++++++++++- src/platform.ts | 73 +++++++++++++---------- 5 files changed, 152 insertions(+), 114 deletions(-) diff --git a/chrome/dist/background.js b/chrome/dist/background.js index 6b61b64..81d224e 100644 --- a/chrome/dist/background.js +++ b/chrome/dist/background.js @@ -1969,7 +1969,8 @@ }; } }, filts, ["blocking", "responseHeaders", ...true ? ["extraHeaders"] : []]); - async function deserialize(src) { + var snooze = (n) => new Promise((_) => setTimeout(_, n)); + async function bravedeserialize(src) { if (typeof src != "object") return src; switch (src.cls) { @@ -1977,26 +1978,30 @@ const ret = new FormData(); for (const [key, items] of src.value) { for (const item of items) { - ret.append(key, await deserialize(item)); + ret.append(key, await bravedeserialize(item)); } } return ret; } case "File": { - return new File([await (await fetch(src.value)).blob()], src.name, { + if ("brave" in navigator) + await snooze(1e3); + return new File([src.value], src.name, { lastModified: src.lastModified, type: src.type }); } case "Blob": { - return new Blob([await (await fetch(src.value)).blob()], { + if ("brave" in navigator) + await snooze(1e3); + return new Blob([src.value], { type: src.type }); } case "Object": { const ret = {}; for (const prop in src.value) { - ret[prop] = await deserialize(src.value[prop]); + ret[prop] = await bravedeserialize(src.value[prop]); } return ret; } @@ -2006,8 +2011,9 @@ var bgCorsFetch = async (c, id, input, init) => { if (input.startsWith("//")) input = "https:" + input; - if (init?.body && true) - init.body = await deserialize(init.body); + if (init?.body && true) { + init.body = await bravedeserialize(init.body); + } try { const k = await fetch(input, init); let headersStr = ""; diff --git a/chrome/dist/main.js b/chrome/dist/main.js index 93f988a..11d167c 100644 --- a/chrome/dist/main.js +++ b/chrome/dist/main.js @@ -51,7 +51,7 @@ var define_BUILD_VERSION_default; var init_define_BUILD_VERSION = __esm({ ""() { - define_BUILD_VERSION_default = [0, 256]; + define_BUILD_VERSION_default = [0, 259]; } }); @@ -14206,79 +14206,60 @@ } } } - async function serialize(src) { - if (src instanceof FormData) { - const value = []; - for (const kv of src) - value.push([kv[0], await Promise.all(src.getAll(kv[0]).map(serialize))]); - return { - cls: "FormData", - value - }; - } - if (src instanceof File) { - const { name, type, lastModified } = src; - const value = URL.createObjectURL(src); - return { - cls: "File", - name, - type, - lastModified, - value - }; - } - if (src instanceof Blob) { - const { type } = src; - const value = URL.createObjectURL(src); - return { - cls: "Blob", - type, - value - }; - } - if (src === null || src === void 0 || typeof src != "object") - return src; - const ret = { - cls: "Object", - value: {} - }; - for (const prop in src) { - ret.value[prop] = await serialize(src[prop]); - } - return ret; - } - function cleanupSerialized(src) { - if (typeof src != "object") - return src; - switch (src.cls) { - case "FormData": { - for (const [key, items] of src.value) { - for (const item of items) { - cleanupSerialized(item); - } - } - break; + async function braveserialize(root) { + const transfer = []; + const ser = async (src) => { + if (src instanceof FormData) { + const value = []; + for (const kv of src) + value.push([kv[0], await Promise.all(src.getAll(kv[0]).map(ser))]); + return { + cls: "FormData", + value + }; } - case "File": { - URL.revokeObjectURL(src.value); - break; + if (src instanceof File) { + const { name, type, lastModified } = src; + const value = await src.arrayBuffer(); + transfer.push(value); + return { + cls: "File", + name, + type, + lastModified, + value + }; } - case "Blob": { - URL.revokeObjectURL(src.value); - break; + if (src instanceof Blob) { + const { type } = src; + const value = await src.arrayBuffer(); + transfer.push(value); + return { + cls: "Blob", + type, + value + }; } - case "Object": { - for (const prop in src.value) { - cleanupSerialized(src.value[prop]); - } + if (src === null || src === void 0 || typeof src != "object") + return src; + const ret = { + cls: "Object", + value: {} + }; + for (const prop in src) { + ret.value[prop] = await ser(src[prop]); } - } + return ret; + }; + return [await ser(root), transfer]; } var corsFetch = async (input, init5, lsn) => { const id = gid++; + let transfer = []; if (init5?.body) { - if (true) - init5.body = await serialize(init5.body); + if (true) { + [init5.body, transfer] = await braveserialize(init5.body); + } } const prom = new Promise((_, rej) => { let gcontroller; @@ -14297,12 +14278,7 @@ let s; s = 0; const cmdbuff = []; - let cleaned = false; lqueue[id] = async (e) => { - if (!cleaned && true && init5?.body) { - cleanupSerialized(init5.body); - cleaned = true; - } if (e.progress) { if (lsn) lsn.dispatchEvent(new CustomEvent("progress", { detail: e.progress })); @@ -14394,7 +14370,7 @@ id, name: "corsFetch", args: [input, init5] - }); + }, transfer); }); return prom; }; diff --git a/chrome/manifest.json b/chrome/manifest.json index be1e59f..9fd3a96 100644 --- a/chrome/manifest.json +++ b/chrome/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "PngExtraEmbedder", "description": "Discover embedded files on 4chan and archives!", - "version": "0.256", + "version": "0.259", "icons": { "64": "1449696017588.png" }, diff --git a/src/background.ts b/src/background.ts index 2865071..7406b67 100644 --- a/src/background.ts +++ b/src/background.ts @@ -54,6 +54,8 @@ if (manifest == 2) } }, filts, ['blocking', 'responseHeaders', ...(execution_mode == "chrome_api" ? ['extraHeaders' as 'blocking'] : [])]); +const snooze = (n: number) => new Promise((_) => setTimeout(_, n)); + async function deserialize(src: any): Promise { if (typeof src != "object") return src; @@ -68,12 +70,16 @@ async function deserialize(src: any): Promise { return ret; } case 'File': { + if ('brave' in navigator) + await snooze(1000); return new File([await (await fetch(src.value)).blob()], src.name, { lastModified: src.lastModified, type: src.type }); } case 'Blob': { + if ('brave' in navigator) + await snooze(1000); return new Blob([await (await fetch(src.value)).blob()], { type: src.type }); @@ -88,13 +94,52 @@ async function deserialize(src: any): Promise { } } +async function bravedeserialize(src: any): Promise { + if (typeof src != "object") + return src; + switch (src.cls) { + case 'FormData': { + const ret = new FormData(); + for (const [key, items] of src.value) { + for (const item of items) { + ret.append(key, await bravedeserialize(item)); + } + } + return ret; + } + case 'File': { + if ('brave' in navigator) + await snooze(1000); + return new File([src.value], src.name, { + lastModified: src.lastModified, + type: src.type + }); + } + case 'Blob': { + if ('brave' in navigator) + await snooze(1000); + return new Blob([src.value], { + type: src.type + }); + } + case 'Object': { + const ret = {} as any; + for (const prop in src.value) { + ret[prop] = await bravedeserialize(src.value[prop]); + } + return ret; + } + } +} + const pendingFetches = new Map(); const bgCorsFetch = async (c: MessagePort, id: number, input: string, init?: RequestInit) => { if (input.startsWith('//')) // firefox?? input = 'https:' + input; - if (init?.body && execution_mode == "chrome_api") - init.body = await deserialize(init.body); + if (init?.body && execution_mode == "chrome_api") { + init.body = await bravedeserialize(init.body); + } try { const k = await fetch(input, init); @@ -165,7 +210,7 @@ const bgCorsFetch = async (c: MessagePort, id: number, input: string, init?: Req } e.close(); reader?.releaseLock(); - } catch(e) { + } catch (e) { const err = e as Error; c.postMessage({ id, diff --git a/src/platform.ts b/src/platform.ts index f875e2c..d6a52ee 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -184,42 +184,59 @@ async function serialize(src: any): Promise { return ret; } -function cleanupSerialized(src: any) { - if (typeof src != "object") - return src; - switch (src.cls) { - case 'FormData': { - for (const [key, items] of src.value) { - for (const item of items) { - cleanupSerialized(item); - } - } - break; +async function braveserialize(root: any): Promise { + const transfer: Transferable[] = []; + const ser = async (src: any): Promise => { + if (src instanceof FormData) { + const value = []; + for (const kv of src) + value.push([kv[0], await Promise.all(src.getAll(kv[0]).map(ser))]); + return { + cls: 'FormData', value, + }; } - case 'File': { - URL.revokeObjectURL(src.value); - break; + if (src instanceof File) { + const { name, type, lastModified } = src; + const value = await src.arrayBuffer(); + transfer.push(value); + return { + cls: 'File', + name, type, lastModified, value, + }; } - case 'Blob': { - URL.revokeObjectURL(src.value); - break; + if (src instanceof Blob) { + const { type } = src; + const value = await src.arrayBuffer(); + transfer.push(value); + return { + cls: 'Blob', type, value, + }; } - case 'Object': { - for (const prop in src.value) { - cleanupSerialized(src.value[prop]); - } + if (src === null || src === undefined || typeof src != "object") + return src; + const ret = { + cls: 'Object', + value: {} + } as any; + for (const prop in src) { + ret.value[prop] = await ser(src[prop]); } - } + return ret; + }; + + return [await ser(root), transfer]; } export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTarget) => { const id = gid++; + let transfer: Transferable[] = []; if (init?.body) { // Chrom* can't pass around FormData and File/Blobs between // the content and bg scripts, so the data is passed through bloburls - if (execution_mode == "chrome_api") - init.body = await serialize(init.body); + if (execution_mode == "chrome_api") { + [init.body, transfer] = await braveserialize(init.body); + } } const prom = new Promise>>((_, rej) => { @@ -247,13 +264,7 @@ export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTa s = 0; const cmdbuff: any[] = []; - let cleaned = false; lqueue[id] = (async (e: any) => { - if (!cleaned && execution_mode == "chrome_api" && init?.body) { - cleanupSerialized(init.body); - cleaned = true; - } - // this is computed from the background script because the content script may // request everything to be delivered in one chunk, defeating the purpose if (e.progress) { @@ -360,7 +371,7 @@ export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTa port1.postMessage({ id, name: 'corsFetch', args: [input, init] - }); + }, transfer); }); return prom; };