简体   繁体   中英

Google Chrome Extension: Expose variable from injected script via chrome.tabs.executeScript to another script injected the same way

Hopefully, the title is self-explanatory. Basically I'm injecting two scripts on my popup.js and I want to expose a variable defined on one of them so the other script can use it.

This is the way I'm injecting the scripts:

let sortFunction = function (goSortParam) {
    if (goSortParam) {
      chrome.tabs.executeScript(
        null,
        { code: 'var goSortParam=true;' },
        function () {
          chrome.tabs.executeScript(null, { file: 'scripts/ajaxCalls.js' });
          chrome.tabs.executeScript(null, { file: 'scripts/frontEndDev.js' });
        }
      );
    } else {
      chrome.tabs.executeScript(
        null,
        { code: 'var goSortParam=false;' },
        function () {
          chrome.tabs.executeScript(null, { file: 'scripts/frontEndDev.js' });
        }
      );
    }
  };

This is the ajaxCalls.js:

const CONFIG_URL = chrome.extension.getURL('./data/config.json');
const promise = fetch(CONFIG_URL);

promise
  .then(function (response) {
    const processingPromise = response.json();
    return processingPromise;
  })
  .then(function (processedResponse) {
    const configData = processedResponse;
    console.log(configData.tags);
  });

The variable I want to expose is "configData" so "frontEndDev.js" can use it. Any ideas will be very welcome.

Safe approach

Use a special dedicated global variable, which you must define in a common script that runs first, for example:

chrome.tabs.executeScript({ code: 'var globalData = {foo: true}' });
chrome.tabs.executeScript({ file: 'scripts/ajaxCalls.js' });
chrome.tabs.executeScript({ file: 'scripts/frontEndDev.js' });

Then use globalData.whatever to access the data and globalData.whatever = 'anything' to set it. Since this is a standard JS object you can set a key inside even if it wasn't defined initially.

To make it even safer you can use the built-in function that converts objects into proper strings: 'var globalData = ' + JSON.stringify({ foo: true })

Unsafe approach

Share foo as window.foo = 'anything' then use it literally as foo or window.foo - both are the same, but the first one may require you to pacify your linting tool eg /* global foo */ in eslint.

It's unsafe in a content script because a web page can have an element with an id attribute containing the exact name of that variable, which historically creates an implicit global variable accessible both in the page context and in the isolated world of content scripts. Some pages may accidentally or intentionally break extensions by adding such an id and if they do it on the <html> element the variable will be created even for content scripts running at document_start .

The first approach was safe because it explicitly defined a global variable before running any dependent code (using a hardcoded name when defining, accessing, writing) thus overriding a possible implicit variable generated for a DOM element.

Some trivia

  • Such shared data can be used only by code that runs later in time (not simply the one that's "outside" the callback, more info )

  • All content scripts for the given page or frame run in the special "isolated world" of content scripts of this extension so they share globals like window or globalThis or any variables declared in the global scope of any script via var , let , const , class . For example, goSortParam in your code is a global variable so it's available in all content scripts directly. The isolated world is basically a standard JavaScript environment like that of any web page, but it's separate/isolated so variables (or DOM expandos) defined in one environment aren't visible in the other one. Every extension is assigned its own isolated world on every page/frame where its content scripts run.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM