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
37 changes: 37 additions & 0 deletions docs/content/messaging/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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[]`***<br/>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
Expand Down Expand Up @@ -278,6 +312,7 @@ interface Message<
data: GetDataType<TProtocolMap[TType]>;
type: TType;
timestamp: number;
namespace?: string;
}
```

Expand All @@ -293,6 +328,8 @@ Contains information about the message received.

- ***`timestamp: number`***<br/>The timestamp the message was sent in MS since epoch.

- ***`namespace?: string`***<br/>Optional namespace for the message. Used by external libraries to identify message sources.

## `MessageSender`

```ts
Expand Down
67 changes: 67 additions & 0 deletions packages/messaging/src/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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 () => {
Expand Down Expand Up @@ -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<ProtocolMap>();
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([]);
});
});
29 changes: 29 additions & 0 deletions packages/messaging/src/generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
*/
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions packages/messaging/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './types';
export * from './extension';
export { setIgnoreNamespaces, getIgnoreNamespaces } from './generic';
4 changes: 4 additions & 0 deletions packages/messaging/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}