pierrejacques
pierrejacques

Reputation: 31

Is it possible to make sure the codes injected by the content script run first

I'm working on a chrome extension for XHR intercepting.

In order to reach the body of the response I injected some codes to intercept the XmlHttpRequest class.

But it kept missing the first batch of requests as the injected script ran in an unpredictable order (usually the last).

So I wonder if there is a way to make sure the dynamically-injected-script runs earlier than the original scripts of the web page.

The following is the interception module of my content script.

The content script is set to be run at "document_start"

const doIntercept = () => {
  const xhrOverrideScript = document.createElement('script');
  xhrOverrideScript.type = 'text/javascript';
  xhrOverrideScript.innerHTML = INTERCEPT_SCRIPT_SHALL_BE_REPLACED_BY_WEBPACK;
  document.body.prepend(xhrOverrideScript);
}

const tryIntercept = () => {
  if (document.body && document.head) {
    doIntercept();
  } else {
    requestIdleCallback(tryIntercept);
  }
};

const interceptXHR = (onFinish) => {
  requestIdleCallback(tryIntercept);
  onFinish();
}

export default interceptXHR;

Upvotes: 0

Views: 84

Answers (1)

woxxom
woxxom

Reputation: 73526

Remove requestIdleCallback and simply append the script to document.documentElement directly without waiting for a head or a body to appear.

Here's the entire code:

const interceptXHR = () => {
  const el = document.createElement('script');
  el.textContent = INTERCEPT_SCRIPT_SHALL_BE_REPLACED_BY_WEBPACK;
  document.documentElement.appendChild(el);
  el.remove();
};

It'll run synchronously so there's no need for a callback either.
There are more methods but some of them are asynchronous.

There's a relatively popular mistaken idea that one must append script elements to a head or body, not to the root element, but they simply confuse HTML specs (see "content model") with DOM specs that don't impose such a limit.

Upvotes: 1

Related Questions