Pubblicato il 14 settembre, 2023

Accessing a Web Page Variable from a Chrome Extension

AC

Andrea Cassani
@andreacassani

Accessing a Web Page Variable from a Chrome Extension
Photo by Firmbee.com on Unsplash

Let's begin by recognizing that building Chrome extensions can be quite challenging due to their unique characteristics.

For instance, consider the scenario where we want to inject some JavaScript code into a web page and access a pre-existing variable. Well, this isn't straightforward because Chrome extensions' Content scripts operate in an "isolated world", ensuring their content doesn't conflict with the web page or other extensions' content scripts.

Content scripts are files that run in the context of web pages. Utilizing the standard Document Object Model (DOM), they can read details of the web pages visited by the browser, make modifications to them, and exchange information with their parent extension.

But what if we need to access a variable defined in the context of the web page, such as a library used by the website?

<script> Injection Method

The least impractical solution to our problem is injecting a <script> tag into the web page. The content of our script can then access variables defined within the web page's context.

Enough talk; let's look at some code.

manifest.json

manifest.json
{
  ...
  "content_scripts": [
    {
      "js": ["content.js"],
      "matches": ["https://example.com/*"]
    }
  ],
  "web_accessible_resources": [
    {
      "resources": ["inject.js"],
      "matches": ["https://example.com/*"]
    }
  ]
}
manifest.json
{
  ...
  "content_scripts": [
    {
      "js": ["content.js"],
      "matches": ["https://example.com/*"]
    }
  ],
  "web_accessible_resources": [
    {
      "resources": ["inject.js"],
      "matches": ["https://example.com/*"]
    }
  ]
}

In our manifest.json, we specify:

  • Our content script, content.js, which contains the code that will run within the DOM via our extension, isolated from the web page itself.
  • Our injected script, which we will later inject into the web page. Since it is a file within our folder structure, we need to make it accessible to the web page by declaring it within web_accessible_resources, or else the web page won't have permission to access it.

Web-accessible resources are files inside an extension that can be accessed by web pages or other extensions. Extensions typically use this feature to expose images or other assets that need to be loaded in web pages, but any asset included in an extension's bundle can be made web accessible.

Injecting the <script> Tag

Now, inside our content.js file, which will be loaded by our Chrome extension within the web pages specified in our manifest.json, we write the following code.

content.js
function retrievePageVariable() {
  document.dispatchEvent(new CustomEvent("retrievePageVariable", {}));
}
 
function _injectScript() {
  const script = document.createElement("script");
  script.src = chrome.runtime.getURL("inject.js");
  (document.head || document.documentElement).appendChild(script);
 
  document.addEventListener("variableRetrieved", (e) => {
    console.log("variableRetrieved", e.detail);
  });
}
 
_injectScript();
content.js
function retrievePageVariable() {
  document.dispatchEvent(new CustomEvent("retrievePageVariable", {}));
}
 
function _injectScript() {
  const script = document.createElement("script");
  script.src = chrome.runtime.getURL("inject.js");
  (document.head || document.documentElement).appendChild(script);
 
  document.addEventListener("variableRetrieved", (e) => {
    console.log("variableRetrieved", e.detail);
  });
}
 
_injectScript();
inject.js
document.addEventListener("retrievePageVariable", () => {
  document.dispatchEvent(
    new CustomEvent("variableRetrieved", {
      detail: webPageVariable,
    }),
  );
});
inject.js
document.addEventListener("retrievePageVariable", () => {
  document.dispatchEvent(
    new CustomEvent("variableRetrieved", {
      detail: webPageVariable,
    }),
  );
});

The following is a sample web page with a defined webPageVariable:

https://example.com/webpage.html
<html>
  ...
  <script>
    let webPageVariable = 1001;
  </script>
</html>
https://example.com/webpage.html
<html>
  ...
  <script>
    let webPageVariable = 1001;
  </script>
</html>

What this code accomplishes is:

  • Creating a <script> tag
  • Adding the URL of our inject.js script file to its src attribute
  • Appending our created element to the DOM
  • Listening for the variableRetrieved event, which will be triggered by the injected script
  • Finally, we can call retrievePageVariable() to emit the retrievePageVariable event, which will be captured by our injected script, returning the page variable.

How to Test

You can access this project's code on GitHub, clone the repository, and then load the extension in your Chrome browser. You can test the extension by navigating to example.com and clicking on the extension icon in your browser's toolbar. Remember to set webPageVariable = ... in Chrome's console!

Conclusion

Accessing web page variables from a Chrome extension is not straightforward and requires some clever tricks. This can be useful if you want to access a library defined within the web page your extension targets without the need to import it into your manifest.json.

#programmazione

Andrea Cassani

©2023 Andrea Cassani

Ordine dei Medici di Bologna
N. iscrizione 18091
P.IVA 03805791203

Navigazione

Le informazioni contenute nel Sito hanno esclusivamente scopo informativo e in nessun caso costituiscono la formulazione di una diagnosi o la prescrizione di un trattamento. Si raccomanda di chiedere sempre il parere del proprio medico riguardo qualsiasi indicazione riportata.

Contatti

[email protected]