npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@andreadev/bg-script

v1.1.13

Published

Library that helps you communicate between background and content scripts in a Google Chrome extension.

Downloads

18

Readme

bg-script - Library for chrome extension communication

npm (scoped) chrome: 55+

This library will help you communicate between your content scripts and the background script, offering an alternative to the default sendMessage API. The chrome API that do this is not very practical in the way it's layed out, and doesn't allow you to easily get response for asynchronous actions.

This project was inspired by comlink, and it started out as a way for me to better understand Javascript Proxies.

How does it work?

Access background script methods from content script

In your background script, you must create a BackgroundHandler class and pass it an object that contains the properties and methods you want to share:

// background.js

function remoteFunction() {
  return "Executed remotely";
}

let bgHandler = new BackgroundHandler({
  remoteFunction // This is a shorthand for `remoteFunction: remoteFunction`
});

In your content script, you should create a BackgroundScript class and then use it like this:

var bgScript = new BackgroundScript("script-id");

// Use an async function for better code!
async function foo() {
   // Get a reference to the background script connection (which is a proxy)
   let connection = await bgScript.getConnection();
   
   let result = await connection.remoteFunction();

   console.log(result); // --> "Executed remotely"
}

// Execute the function when needed
foo();

Acess content scripts methods from the background script

You can call methods exposed from the content script in a similar way:

// Content Script file

function contentScriptMethod() {
  return "Executed in the content script";
}

var bgScript = new BackgroundScript("my-script" , {
  contentScriptMethod
});

If you have the tabId where the script resides, you can call its methods like this:

// Background script file

var bgHandler = new BackgroundHandler();

async function callScriptMethod(tabId) {
  let connection = await bgHandler.getScriptConnection("my-script", tabId);

  let result = await connection.contentScriptMethod();

  console.log(result); // --> Executed in the content script;
}

Installation

Without bundler

Download the build/bgscript.js file and include it in your chrome extension in the following two ways.

In order to use it in your content scripts, include it in your manifest.json as the first content script:

"content_scripts": [{
  "js": ["bgscript.js", "my-content-script.js", ...]
}]

Similarly, for the background, you need to declare it as first script in the "background scripts" section of your manifest file:

"background": {
  "scripts": [ "bgscript.js", "my-background-script.js"]
}

When you do this, the two classes will be automatically available in your scripts.

If you're building an html page for your extension, just add the following tag to the head of your page, before any other script.

<script src='bgscript.js'></script>

With bundler

If you use a bundler, you can install the npm package:

npm install --save @andreadev/bg-script

Then, in your code, you can just import the class that you want to use:

// Background script
import { BackgroundHandler } from '@andreadev/bg-script';

// Content script
import { BackgroundScript } from '@andreadev/bg-script';

How to use it

Get a variable from the background script

Background script:

let shared = {
  variable: 10
}

// This function shows how to use shared variables within the script to avoid problems with object references
function setVariable(val) {
  shared.variable = val;
}

// Initialize the Background script handler passing the object to be shared
let bgHandler = new BackgroundHandler(shared);

Content script:

// Initialize the background script object
let bgScript = new BackgroundScript();

async function foo() {
  // Get a connection to the background script
  let connection = await bgScript.getConnection();

  // Get the variable from the background script
  let variable = await connection.variable;

  console.log(variable);
}

foo();

Execute a method from the background script

Background script:

var variable = null;

function setVariable(val) {
  variable = val;
}

function showVariable() {
  return variable;
}

let shared = {
  setVariable,
  showVariable
}

// Initialize the Background script handler passing the object to be shared
let bgHandler = new BackgroundHandler(shared);

Content Script:

let bgScript = new BackgroundScript();

async function foo() {
  let connection = await bgScript.getConnection();

  await connection.setVariable("Hello world");

  let variable = await connection.showVariable();

  console.log(variable);
}

foo();

Shortcut for setting a shared variable

Instead of creating a setter function and using it like I showed in the examples above, if the variable you want to change is shared, you can do it this way:

Background script:

let shared = {
  variable: null
}

let bgHandler = new BackgroundHandler(shared);

Content script:

let bgScript = new BackgroundScript();

async function foo() {
  let connection = await bgScript.getConnection();

  // Set the variable. The brackets are there to avoid syntax errors.
  await (connection.variable = "Hello world");

  // Show the new variable value
  console.log(await connection.variable);
}

foo();

Note that when you set a variable, the new value will be returned (just like when you set a normal variable). This means that doing it this way will give you the same result as before:

  ...
  // Set the variable and log its new value
  console.log(await (connection.variable = "Hello world"));
  ...

Communicate with the content scripts

From version 1.1.0, you can do all the aforementioned actions from the background script too!

By default, the scripts are associated with their tab ids. For this reason, you should first know which tab you want to communicate with. If you have this tab id in a variable called "tabId", then you can do the following:

// Background script
var bgHandler = new BackgroundHandler();

// ...

async function callContentScript(tabId) {
  let connection = await bgHandler.getScriptConnection("script-id", tabId);
  await connection.remoteMethod(); // This method resides in the content script.
}

The first variable for the getScriptConnection method is the script ID. This must be set in the content script when a new BackgroundScript class is created:

// Content script

var bgScript = new BackgroundScript("script-id", {
  remoteMethod
});

function remoteMethod() {
  return "Method in the content script";
}

API Reference

BackgroundHandler class

Class creation:

var bgHandler = new BackgroundHandler( [exposed-data], [options] );

Parameters: | Parameter | Description | | --------- | ----------- | | [exposed-data] | Object (optional) - An object containing all the properties and methods that will be exposed to the content scripts. This are the limitations: do not put a property (or method) called "then" or "$getMyTabId", because they will be rejected. Also, if you expose a property, it must be JSON-friendly to be correctly received by other scripts. All exposed methods should also return JSON-friendly values in order to work correctly. | | [options] | Object (optional) - An object that will enable further customization. | [options.errorCallback] | function - A callback that will be fired whenever there is an error in the background handler. It will get passed an object with some details of the error: an errorId and an error (the error description).|

Events:

| Name | Details | Description | | ---- | ------- | ----------- | | connectionreceived | { scriptId, tabId } | This event fires when a script has successfully connected to the background handler. | | connectionended | { scriptId, tabId } | This event fires when a script has succesfully disconnected from the background handler. |

In this page you can find more information about the connection lifecycle.

BackgroundScript class

Class creation:

var bgScript = new BackgroundScript( [script-id], [exposed-data], [options] );

Parameters:

| Parameter | Description | | --------- | ----------- | | [script-id] | String (optional) - A unique ID for this script. By default, this id will be tab-specific, so that you can have multiple tabs with the same script using the same script id. If omitted, a unique id will be generated | | [exposed-data] | Object (optional) - An object containing all the properties and methods that will be exposed to the Background script. You can put almost everything here, but just avoid to insert a "then" method, because it will be ignored. Also remember that if you want to directly get a remote property, it must be JSON-friendly, so don't insert properties that cannot be converted to JSON. | | [options] | Object (optional) - An object with some options to customize how the script work | | [options.context] | String - One of "content" (default), "devtools" and "tab-agnostic". If the value is "content", the script id will be associated with the current tab id. If you want to use this library from a devtools script, then you must set this option to "devtools" to automatically associate the script id with the inspected tab id. If the value is "tab-agnostic" the script id won't be associated to any tab id, so you won't be able to create another connection with the same script id. |

Events:

| Name | Description | | ---- | ----------- | | connected | The script has succesfully connected to the background handler. Since the first connection is done when you create the class instance, this event will only fire for the following connections and not for the first one. | disconnected | The script has succesfully disconnected from the background handler. |

Connection proxy

Get a connection to the background script:

// Content script
let bgScript = new BackgroundScript("script-id");
//...
let connection = await bgScript.getConnection();

Get a connection to a content script:

// Background script
let bgHandler = new BackgroundHandler();
// ...
let connection = await bgHandler.getScriptConnection("script-id", tabId);

Also, if you're in a content script, you can retrieve your tabId by calling this method:

let connection = await bgScript.getConnection();

let tabId = await connection.$getMyTabId();

Using the sendMessage API alongside this library

From version 1.1.0, there is no limitation on how to use the "sendMessage" API, since this library is now using long lived connections with ports. If you want to create a separate port to the background script, just avoid to start its name with "bgscript", to ensure that the bgscript library does not mistake it as its private connection.