Synchronously retrieve stored data from content scripts

I am currently working on a chrome extension, and the source code is available on Github . The goal is to add custom Javascript to your web pages.

Currently, I store each custom Javascript Inject in localStorage and is called from them. I set run_at to document_start .

I use this to get saved injections from a background script:

chrome.extension.sendMessage({method:"get_injects"},function(injects){ for(index in injects){ if(/^items\./.test(index)){ itemJSON = injects[index]; //if(window.location.host.toString().indexOf(itemJSON.url)){ if(window.location.host.toString().match(itemJSON.url + '$')){ var js = itemJSON.js.toString(); eval(js); } } } }); 

Problem

I want to run Inject scripts exactly before loading the document. But using the method presented, the control will pass chrome.extension.sendMessage and will not wait to receive an injects response. Thus, eval(js); will be executed in the middle of the page load. How can I solve this problem so that I can embed it before the page loads?

+6
source share
2 answers

In Chrome, each tab launches in its own process. The background page is launched during the extension process, which is different from the one you are connecting. Therefore, I am afraid that there cannot be a truly synchronous solution.

Even using chrome.storage (which does not have a source restriction and therefore does not need a background page) will be asynchronous.

But here is a solution that will work for most pages:

  • If the required data is in the localStorage page, go to 6
  • remove everything from page
  • perform an asynchronous data request
  • when you have the data, save it in the localStorage page (and not in the background).
  • refresh page with the same url
  • profit
+4
source

There is a way to get an arbitrary amount of data synchronously from the background page to the current script content. You should avoid blocking the code synchronously in your extension, so I won’t give you sample code to prevent copying to this in production code.

Flow:

  • Use synchronous XMLHttpRequest in the content of the script (fake URL) to initiate these steps.
  • In the background, use chrome.webRequest.onBeforeRequest to intercept this request.
  • Receive data synchronously, for example. from localStorage or a local variable on the source page, convert it to blob, and then convert it to URL using var url = URL.createObjectURL(new Blob([ 'data chunks here' ])); .
  • Use return {redirectUrl: url}; in the onBeforeRequest event to send data.
  • Make sure you end up using URL.revokeObjectURL(url); to free the resources used by the data.

And fnally, avoid synchronous, blocking code if possible!

0
source

All Articles