Browse Source

Transfer files between iframe more efficiently on chrome and works on brave

pull/46/head
coomdev 2 years ago
parent
commit
cb12a65a8f
  1. 20
      chrome/dist/background.js
  2. 120
      chrome/dist/main.js
  3. 2
      chrome/manifest.json
  4. 51
      src/background.ts
  5. 73
      src/platform.ts

20
chrome/dist/background.js

@ -1969,7 +1969,8 @@
}; };
} }
}, filts, ["blocking", "responseHeaders", ...true ? ["extraHeaders"] : []]); }, filts, ["blocking", "responseHeaders", ...true ? ["extraHeaders"] : []]);
async function deserialize(src) { var snooze = (n) => new Promise((_) => setTimeout(_, n));
async function bravedeserialize(src) {
if (typeof src != "object") if (typeof src != "object")
return src; return src;
switch (src.cls) { switch (src.cls) {
@ -1977,26 +1978,30 @@
const ret = new FormData(); const ret = new FormData();
for (const [key, items] of src.value) { for (const [key, items] of src.value) {
for (const item of items) { for (const item of items) {
ret.append(key, await deserialize(item)); ret.append(key, await bravedeserialize(item));
} }
} }
return ret; return ret;
} }
case "File": { 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, lastModified: src.lastModified,
type: src.type type: src.type
}); });
} }
case "Blob": { 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 type: src.type
}); });
} }
case "Object": { case "Object": {
const ret = {}; const ret = {};
for (const prop in src.value) { for (const prop in src.value) {
ret[prop] = await deserialize(src.value[prop]); ret[prop] = await bravedeserialize(src.value[prop]);
} }
return ret; return ret;
} }
@ -2006,8 +2011,9 @@
var bgCorsFetch = async (c, id, input, init) => { var bgCorsFetch = async (c, id, input, init) => {
if (input.startsWith("//")) if (input.startsWith("//"))
input = "https:" + input; input = "https:" + input;
if (init?.body && true) if (init?.body && true) {
init.body = await deserialize(init.body); init.body = await bravedeserialize(init.body);
}
try { try {
const k = await fetch(input, init); const k = await fetch(input, init);
let headersStr = ""; let headersStr = "";

120
chrome/dist/main.js

@ -51,7 +51,7 @@
var define_BUILD_VERSION_default; var define_BUILD_VERSION_default;
var init_define_BUILD_VERSION = __esm({ var init_define_BUILD_VERSION = __esm({
"<define:BUILD_VERSION>"() { "<define:BUILD_VERSION>"() {
define_BUILD_VERSION_default = [0, 256]; define_BUILD_VERSION_default = [0, 259];
} }
}); });
@ -14206,79 +14206,60 @@
} }
} }
} }
async function serialize(src) { async function braveserialize(root) {
if (src instanceof FormData) { const transfer = [];
const value = []; const ser = async (src) => {
for (const kv of src) if (src instanceof FormData) {
value.push([kv[0], await Promise.all(src.getAll(kv[0]).map(serialize))]); const value = [];
return { for (const kv of src)
cls: "FormData", value.push([kv[0], await Promise.all(src.getAll(kv[0]).map(ser))]);
value 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;
} }
case "File": { if (src instanceof File) {
URL.revokeObjectURL(src.value); const { name, type, lastModified } = src;
break; const value = await src.arrayBuffer();
transfer.push(value);
return {
cls: "File",
name,
type,
lastModified,
value
};
} }
case "Blob": { if (src instanceof Blob) {
URL.revokeObjectURL(src.value); const { type } = src;
break; const value = await src.arrayBuffer();
transfer.push(value);
return {
cls: "Blob",
type,
value
};
} }
case "Object": { if (src === null || src === void 0 || typeof src != "object")
for (const prop in src.value) { return src;
cleanupSerialized(src.value[prop]); 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) => { var corsFetch = async (input, init5, lsn) => {
const id = gid++; const id = gid++;
let transfer = [];
if (init5?.body) { if (init5?.body) {
if (true) if (true) {
init5.body = await serialize(init5.body); [init5.body, transfer] = await braveserialize(init5.body);
}
} }
const prom = new Promise((_, rej) => { const prom = new Promise((_, rej) => {
let gcontroller; let gcontroller;
@ -14297,12 +14278,7 @@
let s; let s;
s = 0; s = 0;
const cmdbuff = []; const cmdbuff = [];
let cleaned = false;
lqueue[id] = async (e) => { lqueue[id] = async (e) => {
if (!cleaned && true && init5?.body) {
cleanupSerialized(init5.body);
cleaned = true;
}
if (e.progress) { if (e.progress) {
if (lsn) if (lsn)
lsn.dispatchEvent(new CustomEvent("progress", { detail: e.progress })); lsn.dispatchEvent(new CustomEvent("progress", { detail: e.progress }));
@ -14394,7 +14370,7 @@
id, id,
name: "corsFetch", name: "corsFetch",
args: [input, init5] args: [input, init5]
}); }, transfer);
}); });
return prom; return prom;
}; };

2
chrome/manifest.json

@ -2,7 +2,7 @@
"manifest_version": 3, "manifest_version": 3,
"name": "PngExtraEmbedder", "name": "PngExtraEmbedder",
"description": "Discover embedded files on 4chan and archives!", "description": "Discover embedded files on 4chan and archives!",
"version": "0.256", "version": "0.259",
"icons": { "icons": {
"64": "1449696017588.png" "64": "1449696017588.png"
}, },

51
src/background.ts

@ -54,6 +54,8 @@ if (manifest == 2)
} }
}, filts, ['blocking', 'responseHeaders', ...(execution_mode == "chrome_api" ? ['extraHeaders' as 'blocking'] : [])]); }, filts, ['blocking', 'responseHeaders', ...(execution_mode == "chrome_api" ? ['extraHeaders' as 'blocking'] : [])]);
const snooze = (n: number) => new Promise<void>((_) => setTimeout(_, n));
async function deserialize(src: any): Promise<any> { async function deserialize(src: any): Promise<any> {
if (typeof src != "object") if (typeof src != "object")
return src; return src;
@ -68,12 +70,16 @@ async function deserialize(src: any): Promise<any> {
return ret; return ret;
} }
case 'File': { case 'File': {
if ('brave' in navigator)
await snooze(1000);
return new File([await (await fetch(src.value)).blob()], src.name, { return new File([await (await fetch(src.value)).blob()], src.name, {
lastModified: src.lastModified, lastModified: src.lastModified,
type: src.type type: src.type
}); });
} }
case 'Blob': { case 'Blob': {
if ('brave' in navigator)
await snooze(1000);
return new Blob([await (await fetch(src.value)).blob()], { return new Blob([await (await fetch(src.value)).blob()], {
type: src.type type: src.type
}); });
@ -88,13 +94,52 @@ async function deserialize(src: any): Promise<any> {
} }
} }
async function bravedeserialize(src: any): Promise<any> {
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<MessagePort, { [id in number]: { fetchFully: boolean } }>(); const pendingFetches = new Map<MessagePort, { [id in number]: { fetchFully: boolean } }>();
const bgCorsFetch = async (c: MessagePort, id: number, input: string, init?: RequestInit) => { const bgCorsFetch = async (c: MessagePort, id: number, input: string, init?: RequestInit) => {
if (input.startsWith('//')) // firefox?? if (input.startsWith('//')) // firefox??
input = 'https:' + input; input = 'https:' + input;
if (init?.body && execution_mode == "chrome_api") if (init?.body && execution_mode == "chrome_api") {
init.body = await deserialize(init.body); init.body = await bravedeserialize(init.body);
}
try { try {
const k = await fetch(input, init); const k = await fetch(input, init);
@ -165,7 +210,7 @@ const bgCorsFetch = async (c: MessagePort, id: number, input: string, init?: Req
} }
e.close(); e.close();
reader?.releaseLock(); reader?.releaseLock();
} catch(e) { } catch (e) {
const err = e as Error; const err = e as Error;
c.postMessage({ c.postMessage({
id, id,

73
src/platform.ts

@ -184,42 +184,59 @@ async function serialize(src: any): Promise<any> {
return ret; return ret;
} }
function cleanupSerialized(src: any) { async function braveserialize(root: any): Promise<any> {
if (typeof src != "object") const transfer: Transferable[] = [];
return src; const ser = async (src: any): Promise<any> => {
switch (src.cls) { if (src instanceof FormData) {
case 'FormData': { const value = [];
for (const [key, items] of src.value) { for (const kv of src)
for (const item of items) { value.push([kv[0], await Promise.all(src.getAll(kv[0]).map(ser))]);
cleanupSerialized(item); return {
} cls: 'FormData', value,
} };
break;
} }
case 'File': { if (src instanceof File) {
URL.revokeObjectURL(src.value); const { name, type, lastModified } = src;
break; const value = await src.arrayBuffer();
transfer.push(value);
return {
cls: 'File',
name, type, lastModified, value,
};
} }
case 'Blob': { if (src instanceof Blob) {
URL.revokeObjectURL(src.value); const { type } = src;
break; const value = await src.arrayBuffer();
transfer.push(value);
return {
cls: 'Blob', type, value,
};
} }
case 'Object': { if (src === null || src === undefined || typeof src != "object")
for (const prop in src.value) { return src;
cleanupSerialized(src.value[prop]); 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) => { export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTarget) => {
const id = gid++; const id = gid++;
let transfer: Transferable[] = [];
if (init?.body) { if (init?.body) {
// Chrom* can't pass around FormData and File/Blobs between // Chrom* can't pass around FormData and File/Blobs between
// the content and bg scripts, so the data is passed through bloburls // the content and bg scripts, so the data is passed through bloburls
if (execution_mode == "chrome_api") if (execution_mode == "chrome_api") {
init.body = await serialize(init.body); [init.body, transfer] = await braveserialize(init.body);
}
} }
const prom = new Promise<Awaited<ReturnType<typeof fetch>>>((_, rej) => { const prom = new Promise<Awaited<ReturnType<typeof fetch>>>((_, rej) => {
@ -247,13 +264,7 @@ export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTa
s = 0; s = 0;
const cmdbuff: any[] = []; const cmdbuff: any[] = [];
let cleaned = false;
lqueue[id] = (async (e: any) => { 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 // this is computed from the background script because the content script may
// request everything to be delivered in one chunk, defeating the purpose // request everything to be delivered in one chunk, defeating the purpose
if (e.progress) { if (e.progress) {
@ -360,7 +371,7 @@ export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTa
port1.postMessage({ port1.postMessage({
id, name: 'corsFetch', args: [input, init] id, name: 'corsFetch', args: [input, init]
}); }, transfer);
}); });
return prom; return prom;
}; };

Loading…
Cancel
Save