Chrome Extension Extension Inter Process — Best Practices

4 min read

Extension Inter-Process Communication Patterns

This document covers communication between Chrome Extensions and external applications, including native messaging and cross-extension communication.

Native Messaging: Connecting to Local Applications

Chrome Extensions can communicate with native applications installed on the user’s computer using the Native Messaging API. This enables extensions to access system-level capabilities that aren’t available through web APIs.

Setting Up Native Messaging

1. Host Manifest File

Create a JSON manifest file (e.g., myhost.json) in a designated directory:

{
  "name": "my_native_app",
  "description": "My Native Application",
  "path": "/path/to/native/app",
  "type": "stdio",
  "allowed_origins": ["chrome-extension://extension-id/"]
}

2. Register in Windows Registry / macOS/Linux

Using connectNative()

// In your extension's background script
const port = chrome.runtime.connectNative("my_native_app");

port.onMessage.addListener((message) => {
  console.log("Received from native app:", message);
});

port.postMessage({ action: "getSystemInfo" });

port.onDisconnect.addListener(() => {
  console.log("Disconnected from native app");
});

JSON STDIO Protocol

Native apps communicate via stdin/stdout using JSON messages:

# Example Python native host
import sys
import json

while True:
    line = sys.stdin.readline()
    if not line:
        break
    
    message = json.loads(line)
    # Process message and send response
    response = {"result": "success", "data": "example"}
    sys.stdout.write(json.dumps(response) + "\n")
    sys.stdout.flush()

Use Cases

Cross-Extension Messaging

Extensions can communicate with other extensions using extensionId.

Sending Messages to Another Extension

// In your extension
const extensionId = "abcdefghijklmnopqrstuvwxyz012345";

chrome.runtime.sendMessage(extensionId, {
  type: "DATA_REQUEST",
  payload: { key: "value" }
}, (response) => {
  console.log("Response:", response);
});

Receiving Messages from Other Extensions

// In the receiving extension's background script
chrome.runtime.onMessageExternal.addListener(
  (message, sender, sendResponse) => {
    if (sender.id === "known-extension-id") {
      // Process message
      sendResponse({ status: "received", data: "processed" });
    }
    return true; // Keep channel open for async response
  }
);

Extension ID Discovery

Extensions must know each other’s IDs. Share IDs through:

Communicating with Web Pages

Use externally_connectable in manifest.json to allow web pages to connect:

{
  "name": "My Extension",
  "externally_connectable": {
    "matches": ["https://example.com/*"],
    "ids": ["*"]
  }
}

Web Page to Extension

// From a web page
const extensionId = "abcdefghijklmnopqrstuvwxyz012345";

chrome.runtime.sendMessage(extensionId, {
  action: "fetchData",
  url: "https://api.example.com/data"
}, (response) => {
  console.log("Extension response:", response);
});

Debugging Native Messaging

Chrome Logs

Common Issues

  1. Manifest Not Found: Verify correct installation location
  2. Permission Denied: Ensure native app has execute permissions
  3. JSON Parse Error: Validate message format (newlines matter)
  4. Timeout: Native app may be unresponsive or crashed

Testing Native App

# Test manually (pipe JSON through stdin)
echo '{"action": "test"}' | ./native_app

Security Considerations

See Also

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.