RTO_form_api.js
What it is
RTO_form_api.js is the foundation helper used by the documentation and most sample projects.
It hides the raw window.postMessage protocol and gives you a clean async API:
detect the extension, open and control tabs (by tabKey), and send predefined commands.
All methods return a Promise. Failures are normalized to an object like { code, message }.
Requirements
- The RTO extension must be installed and enabled.
- Your admin page origin must be allowed in the extension Allow-list.
- Any target host you want to open or automate must also be allow-listed.
RTOForm.detect(1500).
If detection fails, show a friendly “install / enable / allow-list this site” message.
Download
Download RTO_form_api.jsMinimal usage
This is the smallest “copy/paste” snippet that reliably works:
detect the extension, then open a controlled tab using a stable tabKey.
<script src="../RTO_helpers/RTO_form_api.js"></script>
<script>
(async function () {
try {
// detect(timeoutMs:number)
await RTOForm.detect(1500);
// focus=true brings the tab/window to front.
const res = await RTOForm.openTab(
{ "tabKey": "demo", "url": "https://example.com", "focus": true, "newTab": true },
{ "timeoutMs": 20000 }
);
// openTab returns tabId at the root (not inside data.*)
console.log("Controlled tabId:", res && res.tabId);
} catch (e) {
console.error("RTO error:", e && e.code, e && e.message);
}
})();
</script>
RTOForm.openTab() forwards only url, focus and newTab.
If you need to pass extra action fields supported by the extension, use send() (see below).
tabKey per workflow (auth, billing, monitor).
Reusing the same tabKey now cleanly reuses the same controlled tab instead of creating near-simultaneous duplicates.
Optional configuration
Set these globals before loading RTO_form_api.js:
| Global | Type | Default | What it does |
|---|---|---|---|
window.RTO_PAGE_ORIGIN |
string | "rto-page" |
Value placed into outbound messages as origin
|
window.RTO_STRICT_ORIGIN |
boolean | false |
If true, only accepts responses where the payload origin string matches the extension origin string. |
window.RTO_TABKEY |
string | (empty) | Default tabKey if you omit it in calls. |
window.tabKey |
string | (empty) | Legacy fallback for tabKey. |
RTO_EXT_ORIGIN global.
API quick reference
Exports: window.RTOForm with these methods:
| Method | Purpose | Typical timeout |
|---|---|---|
detect(timeoutMs) | Fast check that the extension is listening. | ~1500ms |
openTab(args, opts) | Open/control a tab identified by tabKey. | ~20000ms |
navigate(args, opts) | Navigate an existing controlled tab. | ~20000ms |
focusTab(args, opts) | Bring the controlled tab to front. | ~5000ms |
closeTab(args, opts) | Close the controlled tab. | ~8000ms |
listTabs(args, opts) | List controlled tabs (debug/UI). | ~8000ms |
registerMasterTab(args, opts) | Register the current page tab as the master tab. | ~5000ms |
focusMasterTab(args, opts) | Ask the extension to activate the registered master tab. | ~7000ms |
adoptTab(args, opts) | Attach an existing tabId to a tabKey (advanced). | ~8000ms |
command(msg, opts) | Send a named predefined command (incl. advanced operations). | ~20000ms |
send(type, payload, opts) | Low-level: send any action type + payload. | depends |
bestEffort(promise, opts) | Ignore selected errors for non-critical steps. | n/a |
onStatus(handler) | Subscribe to tabStatus events posted by the extension (status stream). | n/a |
offStatus(handler) | Unsubscribe a previously registered status handler. | n/a |
waitForStatus(filter, timeoutMs) | Resolve with the next tabStatus event matching filter. | timeoutMs default: ~15000ms |
registerMasterTab() on your UI page, then later
call focusMasterTab() from any flow to ask the extension to return to that page tab.
Advanced: using send()
Use send() when you need to pass action-specific fields that are not covered by the convenience wrappers.
(send() forwards all payload fields except timeoutMs, which must be provided in opts.)
<script src="../RTO_helpers/RTO_form_api.js"></script>
<script>
(async function () {
await RTOForm.detect(1500);
// Low-level openTab with explicit timeout handling
await RTOForm.send(
"openTab",
{ "url": "https://example.com", "focus": true, "newTab": true },
{ "tabKey": "demo", "timeoutMs": 20000 }
);
})();
</script>
Allow-list note
RTO_form_api.js is the core helper. If your page also manages the allow-list, use
RTO_domainList.js on top of it. In 7.13.0, page-side allow-list additions go through
allowlistAddRequest and the user confirms on the matching master tab.
tabStatus events (status stream)
Subscribe to the extension's tab lifecycle stream (activation, URL changes, loading/complete…).
<script src="../RTO_helpers/RTO_form_api.js"></script>
<script>
(function () {
function log(ev) {
if (ev && ev.type === "tabStatus") console.log("tabStatus:", ev);
}
RTOForm.onStatus(log);
// Example: wait until a given tabKey reports "complete"
RTOForm.waitForStatus(function (ev) {
return ev && ev.type === "tabStatus" && ev.tabKey === "demo" && ev.event === "complete";
}, 15000).then(function (ev) {
console.log("demo tab is complete:", ev);
});
})();
</script>
Common errors
| Code | Meaning | Typical fix |
|---|---|---|
EXT_NOT_DETECTED |
The extension did not respond. | Check install/enable, then gate with RTOForm.detect(1500) and show guidance. |
DOMAIN_NOT_ALLOWED |
Target host is not allow-listed. | Add the host in the extension Allow-list, then retry. |
NO_CONTROLLED_TAB |
No tab is controlled for this tabKey. |
Call openTab() first (or adoptTab()), verify tabKey. |
TIMEOUT |
No response within timeout. | Increase timeoutMs, confirm the tab finished loading, and retry. |