diff --git a/docs/content/messaging/api.md b/docs/content/messaging/api.md
index 19aa8a5..0bfba50 100644
--- a/docs/content/messaging/api.md
+++ b/docs/content/messaging/api.md
@@ -143,6 +143,40 @@ websiteMessenger.onMessage("initInjectedScript", (...) => {
})
```
+## `getIgnoreNamespaces`
+
+```ts
+function getIgnoreNamespaces(): string[]
+```
+
+Get the current list of ignored namespace prefixes that apply globally to all messaging instances.
+
+**Returns:** Array of namespace prefixes currently being ignored.
+
+## `setIgnoreNamespaces`
+
+```ts
+function setIgnoreNamespaces(namespaces: string[]): void
+```
+
+Set the global list of namespace prefixes to ignore across all messaging instances. Messages with namespaces starting with any of these prefixes will be filtered out and not processed.
+
+**Important:** This function should be called in both your background script and content scripts to ensure consistent filtering across all contexts.
+
+### Parameters
+
+- ***`namespaces: string[]`***
Array of namespace prefixes to ignore globally.
+
+### Example
+
+```ts
+import { setIgnoreNamespaces } from '@webext-core/messaging';
+
+// Call this in both background.js and content scripts
+// Ignore messages from external SDKs
+setIgnoreNamespaces(['external-sdk:', 'analytics:', 'tracking:']);
+```
+
## `ExtensionMessage`
```ts
@@ -278,6 +312,7 @@ interface Message<
data: GetDataType;
type: TType;
timestamp: number;
+ namespace?: string;
}
```
@@ -293,6 +328,8 @@ Contains information about the message received.
- ***`timestamp: number`***
The timestamp the message was sent in MS since epoch.
+- ***`namespace?: string`***
Optional namespace for the message. Used by external libraries to identify message sources.
+
## `MessageSender`
```ts
diff --git a/packages/messaging/src/extension.test.ts b/packages/messaging/src/extension.test.ts
index 18985c5..1d16176 100644
--- a/packages/messaging/src/extension.test.ts
+++ b/packages/messaging/src/extension.test.ts
@@ -2,6 +2,7 @@ import { describe, it, vi, beforeEach, expect } from 'vitest';
import { fakeBrowser } from '@webext-core/fake-browser';
import { ProtocolWithReturn } from './index';
import { defineExtensionMessaging } from './extension';
+import { setIgnoreNamespaces, getIgnoreNamespaces } from './generic';
/**
* This is defined in `@webext-core/fake-browser` when there are no `Browser.runtime.onMessage`
@@ -21,6 +22,8 @@ describe('Messaging Wrapper', () => {
fakeBrowser.reset();
vi.resetAllMocks();
vi.restoreAllMocks();
+ // Clear ignore namespaces before each test
+ setIgnoreNamespaces([]);
});
it('should send and receive messages', async () => {
@@ -163,4 +166,68 @@ describe('Messaging Wrapper', () => {
onMessage1.mock.invocationCallOrder[0],
);
});
+
+ it('should ignore messages with namespaces matching global ignore list', async () => {
+ // Set up ignore list
+ setIgnoreNamespaces(['global-external:', 'sdk:']);
+
+ const { onMessage } = defineExtensionMessaging();
+ const messageHandler = vi.fn();
+
+ onMessage('getLength', messageHandler);
+
+ // Send messages with globally ignored namespaces - these should be filtered out
+ fakeBrowser.runtime.sendMessage({
+ id: 1,
+ timestamp: Date.now(),
+ type: 'getLength',
+ data: 'test',
+ namespace: 'global-external:action',
+ });
+
+ fakeBrowser.runtime.sendMessage({
+ id: 2,
+ timestamp: Date.now(),
+ type: 'getLength',
+ data: 'test',
+ namespace: 'sdk:analytics',
+ });
+
+ // Send a message without globally ignored namespace - this should be processed
+ fakeBrowser.runtime.sendMessage({
+ id: 3,
+ timestamp: Date.now(),
+ type: 'getLength',
+ data: 'test',
+ namespace: 'app:action',
+ });
+
+ // Send a message without any namespace - this should be processed
+ fakeBrowser.runtime.sendMessage({
+ id: 4,
+ timestamp: Date.now(),
+ type: 'getLength',
+ data: 'test',
+ });
+
+ // Wait for async message processing
+ await new Promise(resolve => setTimeout(resolve, 0));
+
+ // Only the non-ignored messages should have triggered the handler
+ expect(messageHandler).toBeCalledTimes(2);
+ });
+
+ it('should manage ignore namespaces correctly', () => {
+ // Initially empty
+ expect(getIgnoreNamespaces()).toEqual([]);
+
+ // Set namespaces
+ const namespaces = ['test:', 'example:'];
+ setIgnoreNamespaces(namespaces);
+ expect(getIgnoreNamespaces()).toEqual(namespaces);
+
+ // Clear namespaces
+ setIgnoreNamespaces([]);
+ expect(getIgnoreNamespaces()).toEqual([]);
+ });
});
diff --git a/packages/messaging/src/generic.ts b/packages/messaging/src/generic.ts
index 1c5b113..989d663 100644
--- a/packages/messaging/src/generic.ts
+++ b/packages/messaging/src/generic.ts
@@ -8,6 +8,26 @@ import {
} from './types';
import { serializeError, deserializeError } from 'serialize-error';
+/**
+ * Global ignore list for message namespaces. Messages with namespaces starting with
+ * any of these prefixes will be filtered out and not processed by any messenger.
+ */
+let ignoreNamespaces: string[] = [];
+
+/**
+ * Set ignore namespaces that apply to all messaging instances.
+ */
+export function setIgnoreNamespaces(namespaces: string[]) {
+ ignoreNamespaces = namespaces;
+}
+
+/**
+ * Get current ignore namespaces.
+ */
+export function getIgnoreNamespaces() {
+ return ignoreNamespaces;
+}
+
/**
* Config required to call `defineGenericMessenger`.
*/
@@ -140,6 +160,15 @@ export function defineGenericMessanging<
`[messaging] "${type as string}" initialized the message listener for this context`,
);
removeRootListener = config.addRootListener(message => {
+ // Check global ignore namespaces
+ if (ignoreNamespaces.length > 0 && message.namespace) {
+ for (const prefix of ignoreNamespaces) {
+ if (message.namespace.startsWith(prefix)) {
+ return;
+ }
+ }
+ }
+
// Validate the message object
if (typeof message.type != 'string' || typeof message.timestamp !== 'number') {
// #77 When the message is invalid, we stop processing the message using return or throw an error (default)
diff --git a/packages/messaging/src/index.ts b/packages/messaging/src/index.ts
index 1e6e7a4..40129e5 100644
--- a/packages/messaging/src/index.ts
+++ b/packages/messaging/src/index.ts
@@ -1,2 +1,3 @@
export * from './types';
export * from './extension';
+export { setIgnoreNamespaces, getIgnoreNamespaces } from './generic';
diff --git a/packages/messaging/src/types.ts b/packages/messaging/src/types.ts
index ff3dc3a..11af6d6 100644
--- a/packages/messaging/src/types.ts
+++ b/packages/messaging/src/types.ts
@@ -114,4 +114,8 @@ export interface Message<
* The timestamp the message was sent in MS since epoch.
*/
timestamp: number;
+ /**
+ * Optional namespace for the message. Used by external libraries to identify message sources.
+ */
+ namespace?: string;
}