How to transfer data between tabs using a Chrome extension
Tags: typescript, softwareengineering, webdev, chrome
Published: 2024-06-14 15:55:27

In today’s interconnected web, it’s common to need communication between different browser tabs, even if they come from different origins. Chrome extensions and the postMessage API make it easy to transfer data between tabs. You can create a Chrome extension using TypeScript to facilitate cross-origin communication. In this guide, I’ll show you how.

### **What You Will Learn**

* Setting up a basic Chrome extension with TypeScript.
    
* Using postMessage API for cross-origin communication.
    

### **Setting up a basic Chrome extension with TypeScript.**

First, let’s set up a basic Chrome extension project with TypeScript.

Follow these steps:

**1\. Create the Project Structure**

I’ll be using this project structure throughout this project.

```css
my-chrome-extension/
├── src/
│   ├── background.ts
│   ├── content.ts
├── manifest.json
├── tsconfig.json
└── package.json
```

**2\. Initialize the**`package.json`**and set up TypeScript.**

Enter the following commands in your terminal.

```powershell
npm init -y
npm install typescript --save-dev
```

Configure TypeScript by adding the following to `tsconfig.json` .

```json
{
    "compilerOptions": {
      "target": "ES6",
      "module": "commonjs",
      "outDir": "./dist",
      "strict": true,
      "esModuleInterop": true
    },
    "include": ["src"]
}
```

**3\. Configure**`manifest.json`**.**

Create a file named `manifest.json` and add the following to configure the manifest.

This is the configuration file of your Chrome Extension.

```json
{
    "manifest_version": 3,
    "name": "My Chrome Extension",
    "version": "1.0",
    "background": {
      "service_worker": "background.js",
      "type": "module"
    },
    "content_scripts": [
      {
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "run_at": "document_start"
      }
    ],
    "permissions": ["tabs"]
}
```

**4\. Create service\_worker and content script.**

Create `src/background.ts` in the folder structure, this will be the service worker of your Chrome Extension, it will keep running in the background.

Create `src/content.ts` in the folder structure, this will be the content script of your Chrome Extension, it gets loaded in every active tab in your browser. Add the following code to the `content.ts` .

```typescript
document.addEventListener('DOMContentLoaded', () => {
    console.log('content.ts loaded');
});
```

**5\. Update**`package.json`**Script to build your Extension.**

```json
  "scripts": {
    "build": "tsc && cp manifest.json dist/"
  },
```

Now enter `npm run build` in your terminal to build the Chrome Extension.

**6\. Load the Extension in Chrome.**

* **Open Chrome and navigate to the Extensions page:** Type `chrome://extensions/` in the address bar and press Enter.
    
* **Enable Developer Mode:** Toggle the switch on the top right to enable Developer Mode.
    
* **Load Unpacked Extension:** Click on the “Load unpacked” button and select the `dist` folder of your project.
    

Your extension should be loaded, and the manifest, background script, and content script should be correctly set up.

To confirm open a tab, open the developer tools of your browser and click on the console tab, there you’ll see the console log which we wrote in the `content.ts` .

This way you can create a simple Chrome Extension.

### **Using postMessage API for cross-origin communication.**

Now let us see how we can communicate between multiple tabs using postMessage API.

This tab inter-communication works not exactly but on a type of basic **PubSub** architecture in which `background.ts` which is our service worker works as a **publisher** and `content.ts` which our content script works as a **subscriber**.

When we send a message from one tab to the content script of that tab the content script forwards that message to the service worker and then the service worker forwards that message to the content script of all other active tabs.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/se101dxl836xw825c183.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qv53n6bxlrgkmqocpszg.png)

Now, let’s code this up. 😄

**1\. Add Chrome types in the TypeScript project.**

To use Chrome API in the TypeScript project we need to install the following package.

```powershell
npm i @types/chrome
```

**2\. Set up the Content Script.**

The content script will listen for the messages from the tab and send them to the background script then the background script will forward the messages to the content scripts of all other active tabs and then the content script will forward the message received from the background script to the tab.

```typescript
 //content.ts : 

document.addEventListener("DOMContentLoaded", () => {console.log("Hello from content script")});

//this will listen to the message from the tab and send it to the background script
window.addEventListener("message", (event) => {
  if (event.source !== window || !event.data.type) return;
  const {type, data} = event.data;
  if (type === "FROM_TAB") {
    chrome.runtime.sendMessage({ type: "FROM_TAB", data });
  }
});

//this will listen to the message from the background script and send it to the tab
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const { type, data } = message;
  if (message.type === "TO_TAB") {
    console.log("content script sending message to tab", message.data);
    window.postMessage({type:'FROM_CONTENT', data}, '*');
  }
});
```

**3\. Set up the background script (service worker).**

```typescript
//background.ts :
//this will listen to the message from the content script and send it to 
//the content scripts of all the active tabs
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const {type, data} = message.data
    if (message.type === 'FROM_TAB') {
      chrome.tabs.query({}, (tabs) => {
        tabs.forEach(tab => {
          if (tab.id && tab.id !== sender.tab?.id) {
            chrome.tabs.sendMessage(tab.id, { type: 'TO_TAB', data  });
          }
        });
      });
    }
  });
```

Now save all the files and enter `npm run build` in your terminal to build the Chrome Extension.

Now go to the Extensions tab and refresh your extension.

To test this out will create a simple HTML page.

```xml
<!-- index.-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2>Waiting for messages:</h2><br />
    <p id="texts"></p>
</body>
<script>
    let texts = document.getElementById('texts');
    window.addEventListener('message', (event) => {
        const {type, data} = event.data;
        if (type === "FROM_CONTENT") {
            console.log(event.data);
            texts.innerHTML += data + '<br />';
        }
    });
</script>
</html>
```

This will listen to all messages and print them on the screen. you can use plugins like **Live Server** to start this HTML file.

Let’s see this in action. 😄

{% embed https://vimeo.com/957731724?share=copy %}

By following this guide, you’ve learned how to set up a Chrome extension with TypeScript and enable seamless cross-origin communication between tabs using the `postMessage` API. This powerful setup allows for a richer, more interconnected user experience across different browser tabs. using postMessage API you can achieve things like scrapping, messaging and many more.

### **Follow Me for More Insights**

If you found this guide helpful and want to learn more about web development, Software Engineering, and other exciting tech topics, follow me here on Medium. I regularly share tutorials, insights, and tips to help you become a better developer. Let’s connect and grow together in this journey of continuous learning!

### **Connect with Me**

* **Twitter**: [https://twitter.com/Bhaskar\_Sawant\_](https://twitter.com/Bhaskar_Sawant_)
    
* **LinkedIn**: [https://www.linkedin.com/in/bhaskar-sawant/](https://www.linkedin.com/in/bhaskar-sawant/)
    
* **GitHub**: [https://github.com/bhaskarcsawant](https://github.com/bhaskarcsawant)
    

Stay tuned for more articles, and feel free to reach out if you have any questions or suggestions for future topics.

Cheers, thanks for reading! 😊

**Happy coding!** 🚀

*This article was originally published on Medium*. It is also available on *Hashnode and Dev.to .*