Skip to content

[iFrame] Add the WebAppFrameUrl and WebAppFrameSrcdoc universal components - #2798

Draft
josemontespg wants to merge 1 commit into
catalogs-shared-sandbox-iframe-packagefrom
catalogs-iframe-components
Draft

josemontespg wants to merge 1 commit into
catalogs-shared-sandbox-iframe-packagefrom
catalogs-iframe-components

Conversation

@josemontespg

@josemontespg josemontespg commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This change adds the two components of the iframe catalog to @a2ui/catalog-iframe as universal components: WebAppFrameUrl, which loads an external web application from an http or https URL, and WebAppFrameSrcdoc, which renders inline HTML. Both render the sandbox proxy in their light DOM, hand it the content once it reports ready, and connect the frame to the surface through WebAppFrameBridge, so the application gets the bound data paths, the allowlists and a MessagePort in the handshake, and its actions, data changes, function calls and resize requests go through the validated host bridge. iframeCatalog exposes them to a MessageProcessor.

The components target A2UI v1.0: they import from @a2ui/web_core/v1_0, the bridge uses the v1.0 ActionPayload and AgentToRendererMessage types, and iframeCatalog is a Catalog for protocol 1.0.

The pieces the components are made of are shared: SandboxedFrameElement (proxy frame rendering, height, proxy handshake, bridge lifecycle across context and content changes, cleanup on removal) and ComponentContextFrameHost (the FrameHost over a universal component's ComponentContext) live in typescript/catalogs/shared/sandbox/ and are exported, so a catalog that adds another sandboxed frame component can build on them.

Changes

  • WebAppFrameUrl (a2ui-web-app-frame-url) and WebAppFrameSrcdoc (a2ui-web-app-frame-srcdoc) with zod APIs that match the catalog schema, iframeCatalog, and the exports in src/index.ts.
  • WebAppFrameUrl only loads http and https URLs and appends the host origin as the origin query parameter; other schemes load nothing and are reported once. WebAppFrameSrcdoc decodes the url_encoded: form, strips author CSP meta tags, injects the strict policy and the link interceptor, and loads nothing for empty content.
  • SandboxedFrameElement: one <iframe> in the light DOM pointing at the sandbox proxy, no sandbox attribute on the proxy frame (the inner frame the proxy creates runs with allow-scripts allow-forms allow-modals and never allow-same-origin), title from accessibility.label, height applied to the element with app-driven resizing through FrameSizing, proxy-ready listening and resource sending, bridge reconnection when the context or the content changes, teardown on disconnect and a new session on re-attach. Styling through --a2ui-sandboxed-frame-* custom properties.
  • ComponentContextFrameHost: data paths through the component's data context, functions through the surface catalog invoker with signal results unwrapped, actions dispatched as events of the component.
  • @a2ui/web_core and lit become peer dependencies (and dev dependencies); the wireit build, test:types and lint scripts depend on typescript/web_core:build.
  • Tests: schema parity of each component with catalog.json; component tests that process the v1.0 catalog examples with a real MessageProcessor, render the elements and play the proxy and the application over an inert same-origin page and the real transferred port; tests of the base class and the host adapter; real-frame scenarios under tests/ that load the real proxy from dist/sandbox/ (served by Karma at /a2ui-sandbox/) and a fixture application in both modes, covering the double-iframe bootstrap and handshake, action, two-way data, function call and resize round trips, and the negative cases (undeclared actions, invalid payloads and unbound data dropped, ambient protocol messages ignored, foreign-origin handshakes ignored, top navigation blocked, no allow-same-origin on the inner frame).
  • README: installation with the peer dependencies, registration with a web renderer next to the basic catalog (components set catalogId to use the frames in a basic surface), the component properties with a message from the catalog examples, styling, and how to write another sandboxed frame component. CHANGELOG entry.

Verification

  • yarn workspaces foreach -R --from @a2ui/catalog-iframe --topological-dev run build: passes from a clean tree.
  • yarn workspace @a2ui/catalog-iframe test: 239 of 239 Karma specs pass in headless Chrome, including the real-frame scenarios.
  • yarn workspace @a2ui/catalog-iframe lint, yarn lint:deps, ./scripts/fix_format.sh --check and python3 scripts/fix_licenses.py --check: pass.
  • yarn pack --dry-run in the package: the components ship under dist/; no tests, test support or fixtures are included.

Pre-launch Checklist

Related to #3157

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the iframeCatalog along with the WebAppFrameUrl and WebAppFrameSrcdoc universal components, which render sandboxed iframe content and connect it to the host via WebAppFrameBridge. It also adds base classes and host adapters (SandboxedFrameElement and ComponentContextFrameHost) to support custom sandboxed frame components, alongside comprehensive unit and integration tests. The feedback highlights a potential security vulnerability in injectContentSecurityPolicy where regular expressions are used to parse and inject elements into HTML, and suggests using DOMParser for a more robust and secure implementation.

Comment thread typescript/catalogs/iframe/src/components/srcdoc_content.ts
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from 2fe370d to 5264f2a Compare September 25, 2026 06:25
@josemontespg
josemontespg added this pull request to stack #2804 September 25, 2026 18:11
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from 5264f2a to 5d0ea7d Compare September 25, 2026 18:37
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch 2 times, most recently from 8fc76cb to b6c8505 Compare October 1, 2026 20:11
@josemontespg
josemontespg removed this pull request from stack #2804 October 1, 2026 20:12
@josemontespg
josemontespg added this pull request to stack #2940 October 1, 2026 20:12
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from b6c8505 to e1c127e Compare October 1, 2026 20:43
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from e1c127e to ba0f9ad Compare October 1, 2026 21:42
@josemontespg
josemontespg removed this pull request from stack #2940 October 1, 2026 21:56
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from ba0f9ad to b75ff80 Compare October 1, 2026 21:56
@josemontespg
josemontespg added this pull request to stack #2946 October 1, 2026 21:56
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch 2 times, most recently from f7242a5 to d5cac41 Compare October 1, 2026 22:41
@josemontespg
josemontespg removed this pull request from stack #2946 October 2, 2026 00:35
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from d5cac41 to 4c12b8a Compare October 2, 2026 00:35
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from 259e2cc to c89212a Compare October 5, 2026 19:42
@josemontespg
josemontespg removed this pull request from stack #2951 October 5, 2026 20:45
@josemontespg
josemontespg added this pull request to stack #3011 October 5, 2026 20:45
@josemontespg
josemontespg removed this pull request from stack #3011 October 7, 2026 23:18
@josemontespg
josemontespg changed the base branch from catalogs-shared-sandbox-iframe-package to main October 7, 2026 23:19
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from c89212a to 676109f Compare October 7, 2026 23:19
@josemontespg
josemontespg changed the base branch from main to catalogs-shared-sandbox-iframe-package October 7, 2026 23:19
@josemontespg
josemontespg added this pull request to stack #3055 October 7, 2026 23:19
@josemontespg
josemontespg removed this pull request from stack #3055 October 7, 2026 23:32
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from 676109f to 1c0f3bd Compare October 7, 2026 23:33
@josemontespg josemontespg changed the title feat(catalogs): add the WebAppFrameUrl and WebAppFrameSrcdoc universal components [iFrame] feat(catalogs): add the WebAppFrameUrl and WebAppFrameSrcdoc universal components Oct 7, 2026
@josemontespg
josemontespg added this pull request to stack #3057 October 7, 2026 23:34
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from 1c0f3bd to ca70f69 Compare October 8, 2026 19:25
@josemontespg josemontespg changed the title [iFrame] feat(catalogs): add the WebAppFrameUrl and WebAppFrameSrcdoc universal components [iFrame] Add the WebAppFrameUrl and WebAppFrameSrcdoc universal components Oct 8, 2026
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from ca70f69 to 0bac791 Compare October 8, 2026 20:22
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch 2 times, most recently from a70f9a3 to 7f30e5f Compare October 8, 2026 20:47
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch 2 times, most recently from 86eda65 to 56cc3e2 Compare October 8, 2026 21:34
@josemontespg
josemontespg force-pushed the catalogs-iframe-components branch from 56cc3e2 to 61f98ee Compare October 8, 2026 22:05

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant