Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ bit of import restructring. The API behaviour is mostly unchanged, with just min
for a script that'll be running in the Window context. Learn more about the change [here](https://github.com/zikaari/crx-bridge/issues/11).
- `setNamespace` is not available in any context except `window`, and `allowWindowMessaging` is not available in any context except `content-script`.
- `getCurrentContext` export has been removed.
- `isInternalEndpoint` returns `true` for some new contexts. In summary it'll be `true` for `background`, `content-script`, `devtools`, `popup`, and `options`.
- `isInternalEndpoint` returns `true` for some new contexts. In summary it'll be `true` for `background`, `content-script`, `devtools`, `offscreen`, `popup`, and `options`.
- For messages sent from `background`, message queuing feature can no longer be trusted due to manifest v3 terminating the service worker runtime after certain time. The queue of messages
sent from `background` will be disposed off along with the termination of the said service worker. Queuing still works for messages sent from all other contexts.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
> **`webext-bridge` just joined the Server Side Up family of open source projects.** [Read the announcement →](https://github.com/serversideup/webext-bridge/discussions/74)

# Introduction
**Messaging in web extensions made easy. Batteries included.** Reduce headache and simplify the effort of keeping data in sync across different parts of your extension. `webext-bridge` is a tiny library that provides a simple and consistent API for sending and receiving messages between different parts of your web extension, such as `background`, `content-script`, `devtools`, `popup`, `options`, and `window` contexts.
**Messaging in web extensions made easy. Batteries included.** Reduce headache and simplify the effort of keeping data in sync across different parts of your extension. `webext-bridge` is a tiny library that provides a simple and consistent API for sending and receiving messages between different parts of your web extension, such as `background`, `content-script`, `devtools`, `offscreen`, `popup`, `options`, and `window` contexts.

## Resources
<!-- - **[Website](https://serversideup.net/open-source/webext-bridge/)** overview of the product.
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/1.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ layout: docs

# Introduction

When building a web extension, communication between all pieces of the extension is essential, but complicated. Every browser is slightly different and targeting where to send your message is complicated. This package provides a simple, consistent API for sending messages between the different parts of your web extension, such as `background`, `content-script`, `devtools`, `popup`, `options`, and `window` contexts.
When building a web extension, communication between all pieces of the extension is essential, but complicated. Every browser is slightly different and targeting where to send your message is complicated. This package provides a simple, consistent API for sending messages between the different parts of your web extension, such as `background`, `content-script`, `devtools`, `offscreen`, `popup`, `options`, and `window` contexts.

This pacakge is production ready. We know, because we use it in [Bugflow](https://bugflow.io). While building our extension, we also wrote our book, ["The Easiest Guide to Building Browser Extensions"](https://serversideup.net/building-multi-platform-browser-extensions/) which highlights this package and shows a variety of in-context use cases.

Expand Down
4 changes: 2 additions & 2 deletions docs/content/docs/3.guide/5.security.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ layout: docs
---
# Security

The following note only applies if and only if, you will be sending/receiving messages to/from `window` contexts. There's no security concern if you will be only working with `content-script`, `background`, `popup`, `options`, or `devtools` scope, which is the default setting.
The following note only applies if and only if, you will be sending/receiving messages to/from `window` contexts. There's no security concern if you will be only working with `content-script`, `background`, `popup`, `offscreen`, `options`, or `devtools` scope, which is the default setting.

`window` context(s) in tab `A` get unlocked the moment you call `allowWindowMessaging(namespace)` somewhere in your extension's content script(s) that's also loaded in tab `A`.

Expand All @@ -25,7 +25,7 @@ import { onMessage, isInternalEndpoint } from "webext-bridge/background";
onMessage("getUserBrowsingHistory", (message) => {
const { data, sender } = message;

// Respond only if request is from 'devtools', 'content-script', 'popup', 'options', or 'background' endpoint
// Respond only if request is from 'devtools', 'content-script', 'popup', 'offscreen', 'options', or 'background' endpoint
if (isInternalEndpoint(sender)) {
const { range } = data;
return getHistory(range);
Expand Down
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"content",
"background",
"devtools",
"offscreen",
"script",
"crx",
"bridge"
Expand All @@ -22,7 +23,7 @@
},
"author": "Neek Sandhu <neek.sandhu@outlook.com>",
"scripts": {
"build": "tsup src/index.ts src/background.ts src/content-script.ts src/devtools.ts src/options.ts src/popup.ts src/window.ts --format esm,cjs --dts",
"build": "tsup src/index.ts src/background.ts src/content-script.ts src/devtools.ts src/options.ts src/popup.ts src/offscreen.ts src/window.ts --format esm,cjs --dts",
"watch": "npm run build -- --watch",
"release": "bumpp --commit --push --tag && npm run build && npm publish"
},
Expand Down Expand Up @@ -52,6 +53,10 @@
"import": "./dist/popup.js",
"require": "./dist/popup.cjs"
},
"./offscreen": {
"import": "./dist/offscreen.js",
"require": "./dist/offscreen.cjs"
},
"./window": {
"import": "./dist/window.js",
"require": "./dist/window.cjs"
Expand All @@ -71,6 +76,9 @@
"devtools": [
"dist/devtools.d.ts"
],
"offscreen": [
"dist/offscreen.d.ts"
],
"options": [
"dist/options.d.ts"
],
Expand Down
4 changes: 2 additions & 2 deletions src/internal/endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Endpoint, RuntimeContext } from '../types'

const ENDPOINT_RE = /^((?:background$)|devtools|popup|options|content-script|window)(?:@(\d+)(?:\.(\d+))?)?$/
const ENDPOINT_RE = /^((?:background$)|devtools|popup|offscreen|options|content-script|window)(?:@(\d+)(?:\.(\d+))?)?$/

export const parseEndpoint = (endpoint: string): Endpoint => {
const [, context, tabId, frameId] = endpoint.match(ENDPOINT_RE) || []
Expand All @@ -13,7 +13,7 @@ export const parseEndpoint = (endpoint: string): Endpoint => {
}

export const formatEndpoint = ({ context, tabId, frameId }: Endpoint): string => {
if (['background', 'popup', 'options'].includes(context))
if (['background', 'popup', 'offscreen', 'options'].includes(context))
return context

return `${context}@${tabId}${frameId ? `.${frameId}` : ''}`
Expand Down
2 changes: 1 addition & 1 deletion src/internal/is-internal-endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Endpoint, RuntimeContext } from '../types'

const internalEndpoints: RuntimeContext[] = ['background', 'devtools', 'content-script', 'options', 'popup']
const internalEndpoints: RuntimeContext[] = ['background', 'devtools', 'content-script', 'options', 'offscreen', 'popup']

export const isInternalEndpoint = ({ context: ctx }: Endpoint): boolean => internalEndpoints.includes(ctx)
14 changes: 14 additions & 0 deletions src/offscreen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createEndpointRuntime } from './internal/endpoint-runtime'
import { createStreamWirings } from './internal/stream'
import { createPersistentPort } from './internal/persistent-port'

const port = createPersistentPort('offscreen')
const endpointRuntime = createEndpointRuntime(
'offscreen',
message => port.postMessage(message),
)

port.onMessage(endpointRuntime.handleMessage)

export const { sendMessage, onMessage } = endpointRuntime
export const { openStream, onOpenStreamChannel } = createStreamWirings(endpointRuntime)
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type RuntimeContext =
| 'options'
| 'content-script'
| 'window'
| 'offscreen'

export interface Endpoint {
context: RuntimeContext
Expand Down