0

I have this UserScript in TamperMonkey that I'd like to convert into an extension

let original_fetch = unsafeWindow.fetch;
unsafeWindow.fetch = async (url, init) => {
    let response = await original_fetch(url, init)
    let respo = response.clone();
    // console.log(url)
    if (url.includes("SomeString")) {
        respo.json().then((info) => {
            if (info.step === "lobby") {
                setTimeout(doSomething(info.data), 300);      
            }
        });
    }
    return response;
};

Within my extension, I injected this code with a script element:

let channel = "customChannel";
const oldFetch = window.fetch;

window.fetch = function () {
    return new Promise((resolve, reject) => {
        oldFetch
            .apply(this, arguments)
            .then(async (response) => {
                const json = await response.clone().json();

                const detail = {
                    json,
                    fetch: {
                        url: response.url,
                        status: response.status,
                    },
                };

                window.dispatchEvent(new CustomEvent(channel, { detail }));

                resolve(response);
            })
            .catch((error) => {
                reject(error);
            });
    });
};

Everything works fine except for the fact that the UserScript fetches more requests than the extension.

Can someone explain why and how can I fix this?

EDIT: problem solved

my problem was caused by bad timing, the script was injected after the call was made.

Changing document.head.prepend(script); to document.documentElement.append(script); made it works as intended.

NOTE: Loading the inject script with script.src = ... or script.textContent = ... hasn't made a difference (I decided to use textContent as suggested by wOxxOm)

Thanks everyone who answered and helped me

seintz
  • 1
  • 4
  • Use [document_start](https://developer.chrome.com/extensions/content_scripts#run_time). – wOxxOm Apr 26 '21 at 17:10
  • userscript already has `document_start`, I set the extension's manifest to run at `document_start` but still doesn't work.. and userscript is working fine, my issue is with the web-extension – seintz Apr 26 '21 at 17:14
  • 1
    You need to reload the extension on `about:debugging` page after editing manifest.json. And you need to use textContent when creating the script element, not `src`. – wOxxOm Apr 26 '21 at 17:31

1 Answers1

0

Update: I missed that the code was injected using script element so the following answer relates to the difference with content script injection.


They are executing in different context/scope.

WebExtension content scripts are injected into content context.

Using unsafeWindow in a userscript will run the fetch in page context which is the same as webpage's own JavaScript (there are some difference between userscript mangers thought).

Without unsafeWindow, if you run fetch it will be somehow similar to WebExtension content script (again, there are some difference between userscript mangers).

In a WebExtension, if you want to run fetch in the page context, you can use window.wrappedJSObject e.g. window.wrappedJSObject.fecth()

erosman
  • 7,094
  • 7
  • 27
  • 46
  • looking into what you said, I've found that I should use window.top.fetch() ( new version of content.fetch() ) thanks you very much – seintz Apr 26 '21 at 17:30
  • 1
    The OP's code already runs in the correct page context as indicated in the question ("script element"). Judging by the OP's comment above the problem is caused by something else entirely. – wOxxOm Apr 26 '21 at 17:33
  • sorry but I'm pretty new to all this, but using `window.top.fetch` instead of `window.fetch` seems to have solved my issues – seintz Apr 26 '21 at 17:47
  • If window.top.fetch helps it means that the issue was either 1) related to iframes on the site or 2) your `script` element was using `src` to load the code instead of textContent or 3) it was a timing issue due to document_start. In any case in Firefox it's best to use wrappedJSObject as indicated in the answer + exportFunction, [example](https://stackoverflow.com/a/64817357). – wOxxOm Apr 26 '21 at 17:49
  • the website on which the extension run is a mess so 1) can be the problem, 2) ` script.src = chrome.runtime.getURL("core/utils/injectFetch.js");` so I'd change it to textContent, as of 3) the extension has to work on both firefox and chrome but I'll take a look at that article – seintz Apr 26 '21 at 18:59
  • as of the article you sent, I'm using step 2 (injecting an external script) since I need chrome compatibility (as said above), but I can't find anything related to `textContent` instead of src – seintz Apr 26 '21 at 19:16