API Reference
Overview
RTO uses window.postMessage to communicate between your page and the extension content script.
The extension proxies actions to the background (tabs APIs live there), then responds back to the page.
You can use the raw protocol directly, but we strongly recommend the helper:
RTO_form_api.js.
Events
Events are posted from the extension to the page. They are one-way notifications and do not carry a requestId.
| Event | Direction | Notes |
|---|---|---|
tabStatus |
extension → page |
Status stream for controlled tabs (activated, URL changes, loading/complete, removed, etc.).
Subscribe using RTOForm.onStatus(fn) or listen to window.message directly.
|
<script>
window.addEventListener("message", function (ev) {
var d = ev && ev.data;
if (!d || typeof d !== "object") return;
// Extension-originated status stream:
// { "origin":"rto-extension", "type":"tabStatus", "tabKey":"demo", "tabId":123, "event":"loading|complete|url|activated|removed|...", "url":"https://..." }
if (d.origin === "rto-extension" && d.type === "tabStatus") {
console.log("tabStatus:", d);
}
}, false);
</script>
Actions
Actions are initiated by the page and answered by the extension with a matching requestId.
Each action has a type and a corresponding typeResult reply.
| Action type | Reply type | Description |
|---|---|---|
detect |
detectResult |
Quick check that the extension is present and listening. |
openTab |
openTabResult |
Open/control a tab using a stable tabKey. In 7.13.0, calls are serialized per key to prevent duplicate tabs. |
adoptTab |
adoptTabResult |
Attach a known tabId to a tabKey (advanced). |
navigate |
navigateResult |
Navigate an existing controlled tab. |
focusTab |
focusTabResult |
Bring the controlled tab to front. |
closeTab |
closeTabResult |
Close a controlled tab. |
listTabs |
listTabsResult |
List known controlled tabs (debug/UI). |
allowlistAddRequest |
allowlistAddRequestResult |
Request a host addition from a page; confirmation happens on the matching master tab. |
registerMasterTab |
registerMasterTabResult |
Register the current page tab as master tab for later focus return and visible plugin-side confirmations. |
focusMasterTab |
focusMasterTabResult |
Ask extension background to focus the registered master tab. |
command |
<action>Result (preferred) or commandResult |
Send predefined commands (DOM focus/style/actions, waits, etc.). |
command, the helper expects <action>Result (e.g. waitForSelectorResult),
but will also accept commandResult.
tabKey per workflow.
In 7.13.0, openTab resolves inside a per-key queue, so a second near-simultaneous call reuses the same tab instead of racing into a duplicate.
Helpers
The documentation provides helper wrappers to normalize errors, timeouts, and expected reply types.
The primary helper is RTO_form_api.js.
| Helper method | Signature | What it does |
|---|---|---|
RTOForm.detect(timeoutMs:number=1500) |
() |
Detect the extension quickly. |
RTOForm.openTab(args, opts) |
(args:{ tabKey,url,focus?,newTab? }, opts:{ timeoutMs }) |
Open/control a tab by tabKey. Default focus is true; newTab is opt-in. |
RTOForm.adoptTab(args, opts) |
(args:{ tabKey,tabId }, opts:{ timeoutMs }) |
Attach a known tabId to a tabKey (advanced). |
RTOForm.navigate(args, opts) |
(args:{ url,tabKey?,tabId?,focus? }, opts:{ timeoutMs }) |
Navigate an existing controlled tab. |
RTOForm.focusTab(args, opts) |
(args:{ tabKey?,tabId? }, opts:{ timeoutMs }) |
Focus a controlled tab. |
RTOForm.closeTab(args, opts) |
(args:{ tabKey?,tabId? }, opts:{ timeoutMs }) |
Close a controlled tab. |
RTOForm.listTabs(args, opts) |
(args:{}, opts:{ timeoutMs }) |
List controlled tabs. Typical helper usage: RTOForm.listTabs({}, { "timeoutMs": 8000 }). |
RTOForm.send("allowlistAddRequest", payload, opts) |
(payload:{ host }, opts:{ timeoutMs }) |
Low-level way to request a host addition from a page. Prefer RTO_domainList.js for a friendlier wrapper. |
RTOForm.registerMasterTab(args, opts) |
(args:{ masterKey? }, opts:{ timeoutMs }) |
Register current UI page tab as master tab. |
RTOForm.focusMasterTab(args, opts) |
(args:{ tabId?,masterKey? }, opts:{ timeoutMs }) |
Focus previously registered master tab from plugin background. |
RTOForm.command(msg, opts) |
(msg:{ action,... }, opts:{ tabKey?,tabId?,timeoutMs }) |
Send a command action. |
RTOForm.send(type, payload, opts) |
(type:string, payload:object, opts:object) |
Low-level generic sender. |
RTOForm.bestEffort(promise, opts) |
(promise, opts:{ ignoreCodes? }) |
Ignore selected error codes for non-critical steps. |
RTOForm.onStatus(handler) |
handler(event) |
Subscribe to tabStatus events from the extension (status stream). |
RTOForm.offStatus(handler) |
handler(event) |
Unsubscribe a previously registered status handler. |
RTOForm.waitForStatus(filter, timeoutMs:number=15000) |
filter(event) |
Resolve with the next tabStatus event matching filter. |
Errors
Errors are normalized by the helper to a predictable object with code and message.
| Code | Meaning | Typical fix |
|---|---|---|
TIMEOUT |
No reply within the configured timeout. | Increase timeout, confirm the tab is allowed and responsive, and use longer waits for approval-driven allow-list flows. |
POSTMESSAGE_FAILED |
Failed to postMessage from the page. | Check browser restrictions and frame contexts. |
ACTION_FAILED |
Generic failure returned by the extension. | Inspect raw field (if present) and extension console logs. |
EXT_NOT_DETECTED |
Detect did not receive a response. | Ensure extension is installed/enabled and site is allow-listed. |
DOMAIN_NOT_ALLOWED |
Target host is not allow-listed in the extension. | Request the host through the allow-list flow, approve it on the master tab, then retry. |
Notes
- MV3 constraint: tab events come from the background service worker, not the content script.
- tabStatus stream: treat it as informational; use it to update UI and wait for readiness.
- Security: always validate allow-lists and never accept commands from untrusted origins.