DOM automation API

Safe named actions for real controlled tabs: read, write, wait, highlight, and guide a visible run without arbitrary code execution.
Product model Safe tab control RTO_helpers guidance
What makes this credible

RTO uses named safe DOM actions on controlled tabs instead of arbitrary injected code. That makes the behavior more explainable and easier to trust.

Best helper companions

See RTO_DOM_actions.js, RTO_form_helpers.js, and the visual cue helpers for guided runs.

Basics

  • DOM actions are sent as type:"command" messages (wrapped by RTOForm.command({ action: "...", ... }, opts)).
  • Most actions require { tabKey, selector } in the payload.
  • Top-frame only: DOM actions run in the controlled tab’s top frame (iframes are intentionally ignored).
  • For dynamic pages, always call waitForSelector before click / getText / setValue.
Safety rules you will see in errors
  • PROTECTED_ELEMENT: the extension blocks touching its own injected UI/protected nodes.
  • Sensitive fields are blocked: password/hidden inputs and common credit-card/iban/password-like names.
  • getHtml is sanitized/redacted and typically truncated (for safety + size limits).

Supported actions (canonical)

These are the named actions handled by the content script (called via RTOForm.command({ action: "...", ... }, opts)).

ActionTypical payload fieldsNotes
waitForSelector{ selector, timeoutMs?, pollMs? }Wait until an element exists.
click{ selector }Clicks an element (protected nodes blocked).
focusElement{ selector }Focus an element.
submit{ selector }selector must target a <form>.
setValue{ selector, value }Inputs/textareas/selects/contentEditable; sensitive blocked.
typeText{ selector, text, clear?, delayMs? }Simulated typing; sensitive blocked.
pressKey{ key, selector? }Dispatches key events; focuses selector if provided.
getText{ selector, timeoutMs?, pollMs? }Returns text; supports wait loop.
getValue{ selector, timeoutMs?, pollMs? }Reads value if present (protected blocked).
getAttr{ selector, name, timeoutMs?, pollMs? }Reads an attribute (protected blocked).
getHtml{ selector?, property?, allowBodyFallback? }Sanitized outerHTML; redacts inputs; typically truncated.
setInnerHtml{ selector, html }Sanitizes: removes scripts/iframes/handlers/javascript: URLs.
setChecked{ selector, checked }Checkbox/radio only.
selectOption{ selector, value? , label? , index? , values? }Supports multi-select via values.
selectSetValue{ selector, value }Set a <select> by value.
highlight{ selector, color?, ms?, clear?, mode? }Debug highlight, can clear.
domSetStyle{ selector, style }Allow-list of safe CSS props only.
injectCss{ css }Injects a style tag.
addClass{ selector, className }Adds a class.
overlayCreate{ x?, y?, size?, color?, pulse?, appearance? }Creates a visible overlay cursor (ring or PNG) and may also apply a real CSS cursor via appearance.cursor or appearance.cssCursor.
overlayStyle{ appearance }Changes overlay appearance and/or the real CSS cursor.
overlayMove{ x1,y1,x2,y2,durationMs?,easing?,appearance? }Animated move.
overlayMoveTo{ selector, pad?, durationMs?, easing? }Moves overlay to selector center.
overlayMoveToWait{ selector, timeoutMs?, pollMs?, pad?, durationMs?, easing?, appearance? }Waits for a selector, then moves the overlay; appearance may also be updated.
overlayLabel{ text?, placement?, dx?, dy?, style?, labelStyle?, persist?, show? }Shows or hides the label; supports placement, dx, dy, style/labelStyle, persist, and show.
overlayHide{ destroy?, keepCursor? }Hides or destroys overlay and clears the real CSS cursor unless keepCursor:true.
domExtractBlock{ selector?, selectorList?, nth?, ascend?, root?, rootStrategy?, allowTags?, allowAttrs?, maxDepth?, maxNodes?, maxChars?, visibleOnly?, avoid?, preWait?, timeoutMs?, pollMs? }Extracts a safe HTML/text block.
Note: The JS helpers (like RTO_DOM_actions.js) may add convenience wrappers to RTOForm, but the authoritative list is the action names above.

Common examples

Login pattern

const tabKey = "app";

await RTOForm.waitForSelector({ tabKey: tabKey, selector: "#email" }, { timeoutMs: 8000 });

await RTOForm.setValue({ tabKey: tabKey, selector: "#email", value: "user@example.com" });

// If the target is a password field, it may be blocked by design.
// Prefer manual login or a non-sensitive auth mechanism.
await RTOForm.setValue({ tabKey: tabKey, selector: "#password", value: "••••••••" });

await RTOForm.click({ tabKey: tabKey, selector: "button[type=submit]" });

await RTOForm.waitForSelector({ tabKey: tabKey, selector: "#dashboard" }, { timeoutMs: 15000 });

Read + write HTML

const tabKey = "app";

// Read HTML (property can be "outerHTML", "innerText", "textContent", "value", etc.)
const res = await RTOForm.getHtml({ tabKey: tabKey, selector: "#content", prop: "outerHTML" });
console.log("result:", res);

// Write HTML (sanitized: scripts/handlers/iframes removed)
await RTOForm.setInnerHtml({ tabKey: tabKey, selector: "#content", html: "Hello" });

Modern overlay examples

Use a PNG locator cursor, move it to a real target, then attach a styled label.

window.RTOForm.command({
  action: "overlayCreate",
  x: 120,
  y: 120,
  appearance: {
    kind: "png",
    png: {
      src: "./assets/cursors/maps.png",
      width: 42,
      height: 42
    },
    offsetX: 0,
    offsetY: 0,
    opacity: 1,
    rotateDeg: 0
  }
}, { tabKey: "demo", timeoutMs: 5000 });
window.RTOForm.command({
  action: "overlayLabel",
  text: "Target area",
  placement: "top",
  dx: 0,
  dy: -8,
  persist: true,
  style: {
    fontSize: "14px",
    fontWeight: "600",
    padding: "10px 14px",
    borderRadius: "14px",
    background: "rgba(40,40,60,.95)",
    color: "#fff",
    boxShadow: "0 10px 28px rgba(0,0,0,.25)",
    border: "1px solid rgba(255,255,255,.18)",
    lineHeight: "1.35"
  }
}, { tabKey: "demo", timeoutMs: 4000 });
window.RTOForm.command({
  action: "overlayMoveToWait",
  selector: "#searchBox",
  durationMs: 700,
  easing: "easeInOut",
  timeoutMs: 5000
}, { tabKey: "demo", timeoutMs: 12000 });

Selector tips

  • Prefer stable IDs: #login, #submit.
  • Prefer semantic attributes: [name=email], [data-test=submit], [data-testid].
  • Avoid fragile selectors: div:nth-child(3) > span.
  • If a selector fails, you will often see ELEMENT_NOT_FOUND or TIMEOUT.
  • If the element is inside an iframe, it will typically be unreachable (top-frame only).

Next