From bbc9fae4291d0c2cb3976d158ecd20e0bd2a8ea0 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 15 Mar 2022 10:12:06 +0100 Subject: serialize and deserialize entire Response object when relaying fetch() calls to other contexts using sendMessage --- background/CORS_bypass_server.js | 55 ++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'background') diff --git a/background/CORS_bypass_server.js b/background/CORS_bypass_server.js index 9805d41..d15db54 100644 --- a/background/CORS_bypass_server.js +++ b/background/CORS_bypass_server.js @@ -2,7 +2,7 @@ * This file is part of Haketilo. * * Function: Allow other parts of the extension to bypass CORS by routing their - * request through this background script using one-off messages. + * requests through this background script using one-off messages. * * Copyright (C) 2022 Wojtek Kosior * @@ -43,35 +43,40 @@ */ #FROM common/browser.js IMPORT browser +#FROM common/misc.js IMPORT uint8_to_hex, error_data_jsonifiable -async function get_prop(object, prop, result_object, call_prop=false) { - try { - result_object[prop] = call_prop ? (await object[prop]()) : object[prop]; - } catch(e) { - result_object[`error_${prop}`] = "" + e; - } +/* + * In this file we implement a fetch()-from-background-script service. Code in + * other parts of the extension shall call sendMessage() with arguments to + * fetch() and code here will call fetch() with those arguments and send back + * the response. + * + * We have to convert the Response from fetch() into a JSON-ifiable value and + * then convert it back (using Response() constructor) due (among others) the + * limitations of Chromium's messaging API: + * https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities#data_cloning_algorithm + * + * We also catch possible errors from fetch() (e.g. in case of an invalid URL) + * and send their data in JSON-ifiable form so that the error object can be + * later re-created. + */ + +/* Make it possible to serialize Response object. */ +async function response_data_jsonifiable(response) { + return { + status: response.status, + statusText: response.statusText, + headers: [...response.headers.entries()], + body: uint8_to_hex(new Uint8Array(await response.arrayBuffer())) + }; } -async function perform_download(fetch_data, respond_cb) { +async function perform_download(fetch_data) { try { - const response = await fetch(fetch_data.url); - const result = {}; - - for (const prop of (fetch_data.to_get || [])) - get_prop(response, prop, result); - - const to_call = (fetch_data.to_call || []); - const promises = []; - for (let i = 0; i < to_call.length; i++) { - const response_to_use = i === to_call.length - 1 ? - response : response.clone(); - promises.push(get_prop(response_to_use, to_call[i], result, true)); - } - - await Promise.all(promises); - return result; + const response = await fetch(fetch_data.url, fetch_data.init); + return response_data_jsonifiable(response); } catch(e) { - return {error: "" + e}; + return {error: error_data_jsonifiable(e)}; } } -- cgit v1.2.3