Everything you need to know about getting started.
5 |
6 |
7 |
8 |
9 |
Who started this project?
10 |
This project was originally started by Neek Sandhu (@zikaari) in 2017. Unfortunately time became a constraint and in January 2024, the project was graciously transferred to Server Side Up to be maintained. We're very grateful for Neek Sandhu's contributions and we're excited to carry the torch forward. 🤝
Nope! This is a 100% free and open-source product that you can implement into your web extensions. If you are looking for a full multi-platform web extension template that includes the webext-bridge package and a whole bunch of other helpful tutorials, check out our book!
43 |
44 |
45 |
53 |
54 |
55 |
56 |
57 |
How can I help this project?
58 |
We are totally open to PRs, issues, and ideas! Feel free to visit our GitHub repository and contribute what you think would make this package better!
8 |
--------------------------------------------------------------------------------
/docs/composables/states.ts:
--------------------------------------------------------------------------------
1 | export const usePreferredProgrammingLanguage = () => useState('programming-language', () => '')
--------------------------------------------------------------------------------
/docs/content/docs/1.index.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Messaging in Web Extensions made easy. Batteries included.'
3 | head.title: 'Introduction - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # Introduction
8 |
9 | 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.
10 |
11 | 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.
12 |
13 | This project was originally started by Neek Sandhu (@zikaari) in 2017. Unfortunately time became a constraint and in January 2024, the project was graciously transferred to Server Side Up to be maintained. We're very grateful for Neek Sandhu’s contributions and we're excited to carry the torch forward. 🤝
14 |
15 | Let's get this package installed!
--------------------------------------------------------------------------------
/docs/content/docs/2.getting-started/1.installation.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Quickly install Webext-Bridge using the package manager of your choice.'
3 | head.title: 'Installation - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # Installation
8 |
9 | You can simply install the Webext-Bridge package using the package manager you are most comfortable with.
10 |
11 | ::code-panel
12 | ---
13 | label: NPM Installation
14 | ---
15 | ```bash
16 | $ npm i webext-bridge
17 | ```
18 | ::
19 |
20 | ::code-panel
21 | ---
22 | label: Yarn Installation
23 | ---
24 | ```bash
25 | $ yarn add webext-bridge
26 | ```
27 | ::
28 |
29 | That's it! You are ready to start simply passing messages between the different components of your extension.
30 |
31 | Up next is a quick example for those who want to see some code. Otherwise, jump to the [concepts section](/docs/guide/concepts) to see the full feature set.
--------------------------------------------------------------------------------
/docs/content/docs/2.getting-started/2.quick-example.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Check out some example code before getting started.'
3 | head.title: 'Quick Example - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # Quick Example
8 | Let's quickly send a message from our popup, to our background script.
9 |
10 | ## Popup
11 | In your popup, add the following code:
12 |
13 | ::code-panel
14 | ---
15 | label: Popup
16 | ---
17 | ```javascript
18 | import { sendMessage, onMessage } from "webext-bridge/popup";
19 | const response = await sendMessage("ACTION", {
20 | data: data
21 | }, "background");
22 | ```
23 | ::
24 |
25 | ## Background Service Worker
26 | Now, head over to your background service worker script and add the following code:
27 |
28 | ::code-panel
29 | ---
30 | label: Background Service Worker (background.js)
31 | ---
32 | ```javascript
33 | import { onMessage, sendMessage } from "webext-bridge/background"
34 |
35 | onMessage( "ACTION", runAction );
36 | async function runAction( {data} ){
37 | // process data
38 |
39 | // return data
40 | return {
41 |
42 | };
43 | }
44 | ```
45 | ::
46 |
47 | That's it! You are ready to send messages.
48 |
49 | ## Advantages
50 | There's a lot of advantages to using the `webext-bridge` package. `webext-bridge` handles everything for you as efficiently as possible. No more `chrome.runtime.sendMessage` or `chrome.runtime.onConnect` or `chrome.runtime.connect`
51 |
52 | First, you can specifically target where your message is being sent or handled. Notice in the popup script, we import from `webext-bridge/popup` and in the background service worker, we import from `webext-bridge/background`. Super handy to control how your messages are being processed and where. No funky scoping or messages being processed in the wrong place.
53 |
54 | Second, the code is much cleaner and easy to read since you can easily bind an action to a function. No more massive switch/case statements that you'd have using the built in messaging systems:
55 |
56 | ::code-panel
57 | ---
58 | label: Compare to built in messaging
59 | ---
60 | ```javascript
61 | browser.runtime.onMessage.addListener( ( request, sender, sendResponse ) => {
62 | switch( request.action ){
63 | case "ACTION":
64 | runAction( request.data ).then( sendResponse );
65 | return true;
66 | break;
67 | }
68 | } );
69 | ```
70 | ::
71 |
72 | Also, this is a cross platform solution. This code will work on Firefox, Chrome, Safari, and Edge!
73 |
74 | While this is a very simple example, it shows the power and flexibility of the `webext-bridge` package. We will be diving in a lot more and showing a ton of examples.
75 |
76 | ## Learn how to use "webext-bridge" with our book
77 | We put together a comprehensive guide to help people [build multi-platform browser extensions](https://serversideup.net/building-multi-platform-browser-extensions/). The book covers everything from getting started to advanced topics like messaging, storage, and debugging. It's a great resource for anyone looking to build a browser extension. The book specifically covers how to use `webext-bridge` to simplify messaging in your extension.
--------------------------------------------------------------------------------
/docs/content/docs/3.guide/1.concepts.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Quickly understand the concepts of using the Webext-Bridge package'
3 | head.title: 'Concepts - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # Concepts
8 | A browser extension consists of a lot of moving parts. You essentially have small, microservices that need to communicate with one another in a variety of ways. As your extension grows in size, it gets all the more hairy when it comes to communication.
9 |
10 | When designing [Bugflow](https://bugflow.io), we handle around 15-20 different messages from a popup, background, and content scripts heading in all different directions. With standard, built-in, browser extension messaging, you don't have direct control where the message is sent, and if you have multiple messages, it's hard to efficiently handle all of them. You end up with massive switch case statements and callback chains.
11 |
12 | The goal of the `webext-bridge` package is to make your internal extension messaging a breeze. You can scope where the message is sent, use type-safe protocols, and handle incoming messages the most efficient way possible.
13 |
14 | Let's look at how the `webext-bridge` package allows you to efficiently communicate within your extension.
15 |
16 | ## Extension Communication Contexts
17 | In your extension, you will have multiple contexts that can send and receive messages:
18 |
19 | 
20 |
21 | Each of these contexts allows you to send a message to, or receive an incoming message. The available contexts available within the package are:
22 |
23 | - `content-script`
24 | - `popup`
25 | - `options`
26 | - `background`
27 | - `devtools`
28 |
29 | We will go through each of these contexts, explain how to use them, and what methods are available. In your code, you will just import the module by adding `import { } from 'webext-bridge/{context}'` wherever you need it.
30 |
31 | ## Background Script
32 | The background script context is special within `webext-bridge`. Even if your extension doesn't need a background page or wont be sending/receiving messages in background script.
33 |
34 | `webext-bridge` uses background/event context as staging area for messages, therefore it **must** loaded in background/event page for it to work.
35 |
36 | (Attempting to send message from any context will fail silently if `webext-bridge` isn't available in background page). See [troubleshooting section](/docs/guide/troubleshooting) for more.
--------------------------------------------------------------------------------
/docs/content/docs/3.guide/2.type-safe-protocols.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Keep consistent type with your messaging using the type safe protocols'
3 | head.title: 'Concepts - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # Type Safe Protocols
8 |
9 | We are likely to use `sendMessage` and `onMessage` in different contexts, keeping the type consistent could be hard, and its easy to make mistakes. `webext-bridge` provide a smarter way to make the type for protocols much easier.
10 |
11 | Create `shim.d.ts` file with the following content and make sure it's been included in `tsconfig.json`.
12 |
13 | ::code-panel
14 | ---
15 | label: shim.d.ts
16 | ---
17 | ```ts
18 | import { ProtocolWithReturn } from "webext-bridge";
19 |
20 | declare module "webext-bridge" {
21 | export interface ProtocolMap {
22 | foo: { title: string };
23 | // to specify the return type of the message,
24 | // use the `ProtocolWithReturn` type wrapper
25 | bar: ProtocolWithReturn;
26 | }
27 | }
28 | ```
29 | ::
30 |
31 | Now within the different parts of your extension, you can use the following:
32 |
33 | ::code-panel
34 | ---
35 | label: Content Script
36 | ---
37 | ```ts
38 | import { onMessage } from 'webext-bridge/content-script'
39 |
40 | onMessage('foo', ({ data }) => {
41 | // type of `data` will be `{ title: string }`
42 | console.log(data.title)
43 | }
44 | ```
45 | ::
46 |
47 | ::code-panel
48 | ---
49 | label: Background Worker
50 | ---
51 | ```ts
52 | import { sendMessage } from "webext-bridge/background";
53 |
54 | const returnData = await sendMessage("bar", {
55 | /* ... */
56 | });
57 | // type of `returnData` will be `CustomReturnType` as specified
58 | ```
59 | ::
--------------------------------------------------------------------------------
/docs/content/docs/3.guide/4.examples.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Here are a few examples of how to use the webext-bridge package within your extension.'
3 | head.title: 'Examples - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 | # Examples
7 |
8 | Here are a few common examples of how to use the `webext-bridge` package to communicate within your extension. There are way more possibilities, this should give a quick overview on how it all works together.
9 |
10 | ## sendMessage() and onMessage()
11 | Of the 6 available methods, the [sendMessage()](/docs/api/send-message) and the [onMessage()](/docs/api/on-message) methods are the most commonly used. Let's quickly go over these methods so the examples make a little more sense.
12 |
13 | The [sendMessage()](/docs/api/send-message) method actually sends the message and will be the same no matter what context you are importing it. This method will accept 3 parameters:
14 | - `messageId` - ID of the message that we are sending. I usually set this to an uppercase enum or string value so it's easy to listen for and makes sense.
15 | - `data` - JSON data to send along with the message. Used for processing.
16 | - `destination` - The destination is where we are sending the message to, such as `background`, `popup`, `content-script@{tabId}`, etc.
17 |
18 | Next, we have the [`onMessage()`](/docs/api/on-message) method which listens to an incoming message targeted. The two parameters accepted by this method are:
19 | - `messageId` - ID of the message are listening to. This matches the `messageId` from the `sendMessage()` method.
20 | - `callback` - The callback function used to handle the method.
21 |
22 | There are other methods that are exposed as well, but they are all built off of these two methods. All methods are documented in the [API](/docs/api/send-message).
23 |
24 |
25 | ## Popup -> Background Script
26 | In this example, we send a message from the popup to the background script.
27 |
28 | One thing to note. In all examples, we decouple the `{data}` in the `onMessage()` handler. You don't have to do that. For the most part, it's all you really need access too. However, the `callback` method accepts a JSON object that contains a little more information and is constructed like this:
29 |
30 | ::code-panel
31 | ---
32 | label: Parameter received by the `onMessage()` callback
33 | ---
34 | ```json
35 | {
36 | "sender": {
37 | "context": "popup", // could be any other context
38 | "tabId": null,
39 | "frameId": null
40 | },
41 | "id": "MESSAGE_ID",
42 | "data": {},
43 | "timestamp": 1701876927787
44 | }
45 | ```
46 | ::
47 |
48 | This can be extremely helpful when figuring out where the message came from. I've used the sender.context to determine where the message came from in order to determine the response in some extensions.
49 |
50 | ::code-panel
51 | ---
52 | label: Popup
53 | ---
54 | ```javascript
55 | import { sendMessage } from "webext-bridge/popup";
56 |
57 | const sendToBackground = async () => {
58 | await sendMessage("RECORD_NAME", {
59 | first_name: 'John',
60 | last_name: 'Doe'
61 | }, "background");
62 | }
63 | ```
64 | ::
65 |
66 | ::code-panel
67 | ---
68 | label: Background
69 | ---
70 | ```javascript
71 | import { onMessage } from "webext-bridge/background";
72 |
73 | onMessage( "RECORD_NAME", recordName );
74 | async function recordName( {data} ){
75 | // Do whatever processing you need here.
76 | return {
77 | // Some response here
78 | };
79 | }
80 | ```
81 | ::
82 |
83 | ## Popup -> Content Script
84 |
85 | This example sends a message from the background to a content script. One SUPER important piece to point out, is when messaging a content script, you need to add the `tabId` where the script is located to the end of the destination.
86 |
87 | If you aren't using the [webextension-polyfill](https://www.npmjs.com/package/webextension-polyfill) package, I'd highly recommend it. Otherwise you will have to write an individual extension for each browser you want to support. In this example, we are using the polyfill and referencing the browser through `browser.` (the alternative would be `chrome.`).
88 |
89 | ::code-panel
90 | ---
91 | label: Popup
92 | ---
93 | ```javascript
94 | import { sendMessage } from "webext-bridge/popup";
95 |
96 | function sendToContentScript{
97 | let tabs = await browser.tabs.query({
98 | active: true,
99 | currentWindow: true
100 | });
101 |
102 | const response = await sendMessage("RECORD_NAME", {
103 | first_name: 'John',
104 | last_name: 'Doe'
105 | }, "content-script@"+tabs[0].id);
106 | }
107 | ```
108 | ::
109 |
110 | Note, we are querying the active tab in the current window to grab the `tabId`. Feel free to use whatever method you need to get the `tabId`
111 |
112 | ::code-panel
113 | ---
114 | label: Content
115 | ---
116 | ```javascript
117 | import { onMessage } from "webext-bridge/content-script";
118 |
119 | onMessage( "RECORD_NAME", recordName );
120 | async function recordName( {data} ){
121 | // Do whatever processing you need here.
122 |
123 | return {
124 | // Some response here
125 | };
126 | }
127 | ```
128 | ::
129 |
130 |
131 | ## Content Script -> Background Script
132 | This example sends a message from the content script to the background script.
133 |
134 | ::code-panel
135 | ---
136 | label: Content
137 | ---
138 | ```javascript
139 | import { sendMessage } from "webext-bridge/content-script";
140 |
141 | const sendToBackground = async () => {
142 | const response = await sendMessage('RECORD_NAME', {
143 | first_name: 'John',
144 | last_name: 'Doe'
145 | }, 'background');
146 |
147 | // Handle response
148 | }
149 | ```
150 | ::
151 |
152 | ::code-panel
153 | ---
154 | label: Background
155 | ---
156 | ```javascript
157 | import { onMessage } from "webext-bridge/background";
158 |
159 | onMessage( "RECORD_NAME", recordName );
160 | async function recordName( {data} ){
161 | // Do whatever processing you need here.
162 |
163 | return {
164 | // Some response here
165 | };
166 | }
167 | ```
168 | ::
169 |
170 | Hope these examples help! Definitely check out the [API](/docs/api/send-message) to see all available methods and how to use them within your extension.
--------------------------------------------------------------------------------
/docs/content/docs/3.guide/5.security.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Serious security note, please read.'
3 | head.title: 'Security - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 | # Security
7 |
8 | 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.
9 |
10 | `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`.
11 |
12 | Unlike `chrome.runtime.sendMessage` and `chrome.runtime.connect`, which requires extension's manifest to specify sites allowed to talk with the extension, `webext-bridge` has no such measure by design, which means any webpage whether you intended or not, can do `sendMessage(msgId, data, 'background')` or something similar that produces same effect, as long as it uses same protocol used by `webext-bridge` and namespace set to same as yours.
13 |
14 | So to be safe, if you will be interacting with `window` contexts, treat `webext-bridge` as you would treat `window.postMessage` API. Before you call `allowWindowMessaging`, check if that page's `window.location.origin` is something you expect already.
15 |
16 | If you plan on having something critical, **always** verify the `sender` before responding:
17 |
18 | ::code-panel
19 | ---
20 | label: Verifying an endpoint before responding
21 | ---
22 | ```javascript
23 | import { onMessage, isInternalEndpoint } from "webext-bridge/background";
24 |
25 | onMessage("getUserBrowsingHistory", (message) => {
26 | const { data, sender } = message;
27 |
28 | // Respond only if request is from 'devtools', 'content-script', 'popup', 'options', or 'background' endpoint
29 | if (isInternalEndpoint(sender)) {
30 | const { range } = data;
31 | return getHistory(range);
32 | }
33 | });
34 | ```
35 | ::
--------------------------------------------------------------------------------
/docs/content/docs/3.guide/6.troubleshooting.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Running into issues?'
3 | head.title: 'Troubleshooting - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # Troubleshooting
8 | With all the moving parts, it's easy to run into issues. Here's a few common mistakes.
9 |
10 | ## Doesn't work?
11 | If `window` contexts are not part of the extension, `webext-bridge` works out of the box for messaging between `devtools` <-> `background` <-> `content-script`(s).
12 |
13 | If even that is not working, it's likely that `webext-bridge` hasn't been loaded in background page of your extension, which is used by `webext-bridge` as a relay. If you don't need a background page for yourself, here's bare minimum to get `webext-bridge` going.
14 |
15 | First, add a `background.js` file within your extension. In the background script, add the following code:
16 |
17 | ::code-panel
18 | ---
19 | label: background.js
20 | ---
21 | ```javascript
22 | import "webext-bridge/background";
23 | ```
24 | ::
25 |
26 | Next, include that file within your manifest:
27 |
28 | ::code-panel
29 | ---
30 | label: manifest.json
31 | ---
32 | ```json
33 | {
34 | "background": {
35 | "scripts": ["path/to/transpiled/background.js"]
36 | }
37 | }
38 | ```
39 | ::
40 |
41 | You now have a simple background script within your extension that the `webext-bridge` can use as a staging ground for communicating messages.
42 |
43 | ## Can't send messages to `window`?
44 | Sending or receiving messages from or to `window` requires you to open the messaging gateway in content script(s) for that particular tab.
45 |
46 | Call `allowWindowMessaging()` in any of your content script(s) in that tab and call `setNamespace()` in the script loaded in top frame i.e the `window` context. Make sure that `namespaceA === namespaceB`.
47 |
48 | If you're doing this, read the [security section](/docs/guide/security)
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/docs/content/docs/3.guide/7.resources.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'For more information, check out these resources'
3 | head.title: 'Resources - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # Resources
8 |
9 | The best resource we have to offer regarding building browser extensions is our book, [Building Multi-Platform Browser Extensions](https://serversideup.net/building-multi-platform-browser-extensions/). We go through the whole process and provide templates to get you up and running. All templates use `webext-bridge` and we have tutorials for quite a few common issues that come up.
10 |
11 | - **[Discord](https://serversideup.net/discord)** for friendly support from the community and the team.
12 | - **[GitHub](https://github.com/serversideup/webext-bridge)** for source code, bug reports, and project management.
13 | - **[Get Professional Help](https://serversideup.net/professional-support)** - Get video + screen-sharing help directly from the core contributors.
--------------------------------------------------------------------------------
/docs/content/docs/4.api/1.send-message.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'sendMessage() API Documentation'
3 | head.title: 'sendMessage() - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # sendMessage()
8 |
9 | `sendMessage(messageId: string, data: any, destination: string)`
10 |
11 | Sends a message to some other part of your extension.
12 |
13 | - If there is no listener on the other side an error will be thrown where `sendMessage` was called.
14 |
15 | - Listener on the other may want to reply. Get the reply by `await`ing the returned `Promise`
16 |
17 | - An error thrown in listener callback (in the destination context) will behave as usual, that is, bubble up, but the same error will also be thrown where `sendMessage` was called
18 |
19 | - If the listener receives the message but the destination disconnects (tab closure for exmaple) before responding, `sendMessage` will throw an error in the sender context.
20 |
21 | ## `messageId`
22 |
23 | **Required** | `string`
24 |
25 | Any `string` that both sides of your extension agree on. Could be `get-flag-count` or `getFlagCount` or `GET_FLAG_COUNT`, as long as it's same on receiver's `onMessage` listener.
26 |
27 | ## `data`
28 |
29 | **Required** | `any`
30 |
31 | Any serializable value you want to pass to other side, latter can access this value by refering to `data` property of first argument to `onMessage` callback function.
32 |
33 | ## `destination`
34 |
35 | **Required** | `string`
36 |
37 | The actual identifier of other endpoint.
38 |
39 | Example: `devtools` or `content-script` or `background` or `content-script@133` or `devtools@453`
40 |
41 | `content-script`, `window` and `devtools` destinations can be suffixed with `@` to target specific tab. Example: `devtools@351`, points to devtools panel inspecting tab with id 351.
42 |
43 | For `content-script`, a specific `frameId` can be specified by appending the `frameId` to the suffix `@.`.
44 |
45 | Read [Notes](/docs/api/notes) section to see how destinations (or endpoints) are treated.
46 |
47 | ::note
48 | For security reasons, if you want to receive or send messages to or from `window` context, one of your extension's content script must call `allowWindowMessaging()` to unlock message routing.
49 |
50 | Also call `setNamespace()` in those `window` contexts. Use same namespace string in those two calls, so `webext-bridge` knows which message belongs to which extension (in case multiple extensions are using `webext-bridge` in one page)
51 | ::
--------------------------------------------------------------------------------
/docs/content/docs/4.api/2.on-message.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'onMessage() API Documentation'
3 | head.title: 'onMessage() - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # onMessage()
8 |
9 | Register one and only one listener, per messageId per context. That will be called upon `sendMessage` from other side.
10 |
11 | Optionally, send a response to sender by returning any value or if async a `Promise`.
12 |
13 | ## `messageId`
14 |
15 | **Required** | `string`
16 |
17 | Any `string` that both sides of your extension agree on. Could be `get-flag-count` or `getFlagCount` or `GET_FLAG_COUNT`, as long as it's same in sender's `sendMessage` call.
18 |
19 | ## `callback`
20 |
21 | **Required** | `fn`
22 |
23 | A callback function `webext-bridge` should call when a message is received with same `messageId`. The callback function will be called with one argument, a `message` which has `sender`, `data` and `timestamp` as its properties.
24 |
25 | Optionally, this callback can return a value or a `Promise`, resolved value will sent as reply to sender.
26 |
27 | Read [security note](/docs/guide/security) before using this.
--------------------------------------------------------------------------------
/docs/content/docs/4.api/3.allow-window-messaging.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'allowWindowMessaging() API Documentation'
3 | head.title: 'allowWindowMessaging() - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # allowWindowMessaging()
8 |
9 | ::warning
10 | Caution: Dangerous action
11 | ::
12 |
13 | API available only to content scripts
14 |
15 | Unlocks the transmission of messages to and from `window` (top frame of loaded page) contexts in the tab where it is called.
16 |
17 | `webext-bridge` by default won't transmit any payload to or from `window` contexts for [security](/docs/guide/security) reasons.
18 |
19 | This method can be called from a content script (in top frame of tab), which opens a gateway for messages.
20 |
21 | Once again, `window` = the top frame of any tab. That means **allowing window messaging without checking origin first** will let JavaScript loaded at `https://evil.com` talk with your extension and possibly give indirect access to things you won't want to, like `history` API. You're expected to ensure the safety and privacy of your extension's users.
22 |
23 | ## `namespace`
24 |
25 | **Required** | `string`
26 |
27 | Can be a domain name reversed like `com.github.facebook.react_devtools` or any `uuid`. Call `setNamespace` in `window` context with same value, so that `webext-bridge` knows which payload belongs to which extension (in case there are other extensions using `webext-bridge` in a tab). Make sure namespace string is unique enough to ensure no collisions happen.
--------------------------------------------------------------------------------
/docs/content/docs/4.api/4.set-namespace.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'setNamespace() API Documentation'
3 | head.title: 'setNamespace() - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # setNamespace()
8 | API available to scripts in top frame of loaded remote page.
9 |
10 | Sets the namespace `Bridge` should use when relaying messages to and from `window` context. In a sense, it connects the callee context to the extension which called `allowWindowMessaging()` in it's content script with same namespace.
11 |
12 | ## `namespace`
13 |
14 | **Required** | `string`
15 |
16 | Can be a domain name reversed like `com.github.facebook.react_devtools` or any `uuid`. Call `setNamespace` in `window` context with same value, so that `webext-bridge` knows which payload belongs to which extension (in case there are other extensions using `webext-bridge` in a tab). Make sure namespace string is unique enough to ensure no collisions happen.
--------------------------------------------------------------------------------
/docs/content/docs/4.api/5.open-stream.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'openStream() API Documentation'
3 | head.title: 'openStream() - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # openStream()
8 | ::note
9 | The following API is built on top of `sendMessage` and `onMessage`, basically, it's just a wrapper, the routing and security rules still apply the same way.
10 | ::
11 |
12 | Opens a `Stream` between caller and destination.
13 |
14 | Returns a `Promise` which resolves with `Stream` when the destination is ready (loaded and `onOpenStreamChannel` callback registered).
15 |
16 | ## `channel`
17 |
18 | **Required** | `string`
19 |
20 | `Stream`(s) are strictly scoped `sendMessage`(s). Scopes could be different features of your extension that need to talk to the other side, and those scopes are named using a channel id.
21 |
22 | ## `destination`
23 |
24 | **Required** | `string`
25 |
26 | Same as `destination` in [`sendMessage(msgId, data, destination)`](/docs/api/send-message)
--------------------------------------------------------------------------------
/docs/content/docs/4.api/6.on-open-stream-channel.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'onOpenStreamChannel() API Documentation'
3 | head.title: 'onOpenStreamChannel() - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # onOpenStreamChannel()
8 | ::note
9 | The following API is built on top of `sendMessage` and `onMessage`, basically, it's just a wrapper, the routing and security rules still apply the same way.
10 | ::
11 |
12 | Registers a listener for when a `Stream` opens. Only one listener per channel per context.
13 |
14 | ## `channel`
15 |
16 | **Required** | `string`
17 |
18 | `Stream`(s) are strictly scoped `sendMessage`(s). Scopes could be different features of your extension that need to talk to the other side, and those scopes are named using a channel id.
19 |
20 | ## `callback`
21 |
22 | **Required** | `fn`
23 |
24 | Callback that should be called whenever `Stream` is opened from the other side. Callback will be called with one argument, the `Stream` object, documented below.
25 |
26 | `Stream`(s) can be opened by a malicious webpage(s) if your extension's content script in that tab has called `allowWindowMessaging`, if working with sensitive information use `isInternalEndpoint(stream.info.endpoint)` to check, if `false` call `stream.close()` immediately.
--------------------------------------------------------------------------------
/docs/content/docs/4.api/7.notes.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 'Extra notes when working with webext-bridge'
3 | head.title: 'Notes - Webext-Bridge - Server Side Up'
4 | layout: docs
5 | ---
6 |
7 | # Notes
8 | ::note
9 | Following rules apply to `destination` being specified in `sendMessage(msgId, data, destination)` and `openStream(channelId, initialData, destination)`
10 | ::
11 |
12 | - Specifying `devtools` as destination from `content-script` will auto-route payload to inspecting `devtools` page if open and listening. If devtools are not open, message will be queued up and delivered when devtools are opened and the user switches to your extension's devtools panel.
13 |
14 | - Specifying `content-script` as destination from `devtools` will auto-route the message to inspected window's top `content-script` page if listening. If page is loading, message will be queued up and delivered when page is ready and listening.
15 |
16 | - If `window` context (which could be a script injected by content script) are source or destination of any payload, transmission must be first unlocked by calling `allowWindowMessaging()` inside that page's top content script, since `Bridge` will first deliver the payload to `content-script` using rules above, and latter will take over and forward accordingly. `content-script` <-> `window` messaging happens using `window.postMessage` API. Therefore to avoid conflicts, `Bridge` requires you to call `setNamespace(uuidOrReverseDomain)` inside the said window script (injected or remote, doesn't matter).
17 |
18 | - Specifying `devtools` or `content-script` or `window` from `background` will throw an error. When calling from `background`, destination must be suffixed with tab id. Like `devtools@745` for `devtools` inspecting tab id 745 or `content-script@351` for top `content-script` at tab id 351.
--------------------------------------------------------------------------------
/docs/content/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: marketing
3 | ---
4 |
5 | :marketing-hero
6 |
7 | :marketing-browsers
8 |
9 | :marketing-feature-grid
10 |
11 | :marketing-book
12 |
13 | :marketing-faq
14 |
15 | :marketing-build-in-public
16 |
17 | :marketing-footer
--------------------------------------------------------------------------------
/docs/layouts/docs.vue:
--------------------------------------------------------------------------------
1 |
2 |