Inter-process communication (browser)¶
Audience: Agent
This document describes the postMessage-based protocol implemented by @howfe/inter-frame-messenger and used between the surface map (parent window) and the remote journal reader (popup). Source of truth: inter-frame-messenger/src/index.ts.
Message envelope¶
All messages use the browser’s structured-clone payload shape:
| Field | Type | Meaning |
|---|---|---|
event |
string |
One of MessageTypeEnum values (e.g. 'elite-event', 'open-file:journal'). |
payload |
unknown |
Event-specific data; for elite-event / elite-status validated with isEliteEvent / isStatus from @howfe/elite-dangerous-event-types. |
Receive path: window.addEventListener('message', …) filters by event.origin (see below), then compares event.data.event to the subscribed name, then passes event.data.payload to callbacks.
Send path: target.postMessage({ event, payload }, origin) — for each origin in allowedListenerOrigins (see inter-frame-messenger/src/index.ts lines 104–113).
MessageTypeEnum¶
Defined in inter-frame-messenger/src/index.ts:
| Value | Direction (typical) | Payload |
|---|---|---|
elite-event |
Popup → opener | EliteEvent |
elite-status |
Popup → opener | Status |
message-types-info |
Either | { sendMessageTypes, listenMessageTypes } |
get-message-types |
Either | (triggers info reply) |
open-file:journal |
Opener → popup | (no structured payload in handlers) |
refetch-file:journal |
Opener → popup | — |
poll-file:journal |
Opener → popup | — |
stop-polling:journal |
Opener → popup | — |
open-file:status |
Opener → popup | — |
refetch-file:status |
Opener → popup | — |
poll-file:status |
Opener → popup | — |
stop-polling:status |
Opener → popup | — |
Note: JournalWatcher / StatusWatcher call this.messenger.send(MessageTypeEnum.EliteEvent, event) for journal lines (line 93 in JournalWatcher.ts) — equivalent to sendEliteEvent when the type is allowed.
Parent vs popup construction¶
Popup (remote journal reader)¶
Files: elite-dangerous-remote-journal-reader/ui/src/components/JournalWatchButton.vue, StatusWatchButton.vue.
target = window.opener- Sends:
EliteEvent(journal) orStatus(status file) - Listens:
Open*/Refetch*/Poll*/Stop*for journal or status - Origins:
allowedSenderOrigins: ['*'],allowedListenerOrigins: ['*']in current code — permissive so any opener can control the popup if it sends allowed message types.
Parent (surface map)¶
File: elite-dangerous-surface-map/ui/src/composables/useJournalReader.ts.
target= reference to the popupWindowfromwindow.open('https://edjr.howfe.org', …)- Sends: none of the journal/status command types are registered (
sendMessageTypesis[]); only implicitmessage-types-infohandling from the library constructor - Listens:
EliteEvent,Status - Origins:
allowedSenderOrigins: ['*'],allowedListenerOrigins: ['https://edjr.howfe.org']— incoming messages from any origin are accepted (*); outgoingpostMessageto the popup uses target originhttps://edjr.howfe.org
Security implication: inbound filtering on the parent uses '*' for senders — rely on child origin in practice being the known popup. Tightening to the EDJR origin is a possible hardening step (TODO: Verify if you support multiple embedders).
Sequence: user starts journal feed from map¶
Sequence: journal line parsing (popup)¶
Extending the protocol¶
- Add a new enum value in
inter-frame-messenger/src/index.ts(avoid reusing strings). - Rebuild and publish
@howfe/inter-frame-messenger(or link workspace package). - Update both sender and receiver allowlists (
sendMessageTypes/listenMessageTypes) and handlers. - If payload types are new, extend
@howfe/elite-dangerous-event-types(or a separate package) — do not invent ad-hoc shapes only in one app.
Compatibility¶
- Requires modern
postMessageand (for file picking) File System Access API — Chromium-based browsers / WebView2 align with the assumptions in original-concept.md.