{"id":28373666,"url":"https://github.com/wicg/capability-delegation","last_synced_at":"2026-02-24T05:51:02.681Z","repository":{"id":40244941,"uuid":"294508549","full_name":"WICG/capability-delegation","owner":"WICG","description":"An API to allow developers transfer the ability to use restricted APIs to any target window in the frame tree.","archived":false,"fork":false,"pushed_at":"2024-07-09T07:47:04.000Z","size":112,"stargazers_count":16,"open_issues_count":15,"forks_count":8,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-29T19:57:02.419Z","etag":null,"topics":["activation-delegation","delegation","fullscreen","payment-request"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WICG.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"security_and_privacy_questionnaire.md","support":null}},"created_at":"2020-09-10T19:52:19.000Z","updated_at":"2025-04-09T10:16:49.000Z","dependencies_parsed_at":"2022-08-23T16:40:31.084Z","dependency_job_id":null,"html_url":"https://github.com/WICG/capability-delegation","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/WICG/capability-delegation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WICG%2Fcapability-delegation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WICG%2Fcapability-delegation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WICG%2Fcapability-delegation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WICG%2Fcapability-delegation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WICG","download_url":"https://codeload.github.com/WICG/capability-delegation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WICG%2Fcapability-delegation/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266661993,"owners_count":23964414,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activation-delegation","delegation","fullscreen","payment-request"],"created_at":"2025-05-29T19:40:09.269Z","updated_at":"2025-10-24T14:19:13.439Z","avatar_url":"https://github.com/WICG.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Capability Delegation\n\nTransferring the ability to use restricted APIs to another `window`.\n\n([Draft specification](https://wicg.github.io/capability-delegation/spec.html))\n\n\n## Author\n\nMustaq Ahmed (mustaq@chromium.org,\n[github.com/mustaqahmed](https://github.com/mustaqahmed))\n\n\n## Participate\n\n* Github repository:\n  [WICG/capability-delegation](https://github.com/WICG/capability-delegation)\n* Issue tracker:\n  [WICG/capability-delegation/issues](https://github.com/WICG/capability-delegation/issues/)\n\n\n## Introduction\n\n\"Capability delegation\" means allowing a frame to relinquish its ability to call\na restricted API and transfer the ability to another (sub)frame it trusts. The\nfocus here is a dynamic delegation mechanism which exposes the capability to the\ntarget frame in a time-constrained manner (unlike `\u003ciframe allow=...\u003e` attribute\nwhich is not time-constrained).\n\nThe API proposed here is based on `postMessage()`, where the sender frame uses a\nnew\n[PostMessageOptions](https://html.spec.whatwg.org/multipage/window-object.html#windowpostmessageoptions)\nmember to specify the capability it wants to delegate.\n\n\n## Motivating use-cases\n\nHere are some practical scenarios that are enabled by the Capability Delegation\nAPI.\n\n\n### Secure PaymentRequest processing in a subframe\n\nMany merchant websites perform payment processing through a Payment Service\nProvider (PSP) site (e.g. [Stripe](https://stripe.com)) to comply with security\nand regulatory complexities around card payments.  When the end-user clicks on\nthe \"Pay\" button on the merchant website, the merchant website sends a message\nto a cross-origin `iframe` from the PSP website to initiate payment processing,\nand then the `iframe` uses the [Payment Request\nAPI](https://w3c.github.io/payment-request) to complete the task.\n\nBut sites are only allowed to call the [Payment Request\nAPI](https://w3c.github.io/payment-request) after [transient user\nactivation](https://html.spec.whatwg.org/multipage/interaction.html#transient-activation)\n(a recent click or other interaction) to prevent malicious attempts like\nunattended or repeated payment requests.  Since the user probably clicked on the\nmain site, and not the PSP `iframe`, this would prevent the PSP from using the\nPayment Request API at all.  Browsers today support such payment processing by\nignoring the user activation requirement altogether (see\n[crbug.com/1114218](https://crbug.com/1114218))!\n\nCapability Delegation API provides a way to support this use-case while letting\nthe browser enforce the user activation requirement, as follows:\n\n```javascript\n// Top-frame (merchant website) code\ncheckout_button.onclick = () =\u003e {\n    targetWindow.postMessage(\"process_payment\", {targetOrigin: \"https://example.com\",\n                                                 delegate: \"payment\"\n                                                });\n};\n\n// Sub-frame (PSP website) code\nwindow.onmessage = () =\u003e {\n    const payment_request = new PaymentRequest(...);\n    const payment_response = await payment_request.show();\n    ...\n}\n```\n\n\n### Allowing fullscreen from opener Window click\n\nThis is a\n[work-in-progress](https://groups.google.com/a/chromium.org/g/blink-dev/c/7YkubntWi3Y/m/gwK7fMiEAwAJ)\nin Chrome.\n\nConsider a presentation/slide website where the main \"control panel\" window has\nspawned a few presentation windows, and the user wants to selectively make one\npresentation window fullscreen by clicking on the appropriate button on the main\nwindow (a [feature request\n](https://bugs.chromium.org/p/chromium/issues/detail?id=931966#c5)from a\ndeveloper).  Clicking on the \"control panel\" button does not make the user\nactivation available to the presentation window, so this does not work today.\n\nThe Web does not support this use-case today but Capability Delegation API\nprovides a solution:\n\n```javascript\n// Main window (\"control panel\") code\nlet win1 = open(\"presentation1.html\");\nlet win2 = open(\"presentation2.html\");\n\nbutton1.onclick = () =\u003e win1.postMessage(\"msg\", {targetOrigin: \"https://example.com\",\n                                                 delegate: \"fullscreen\"});\nbutton2.onclick = () =\u003e win2.postMessage(\"msg\", {targetOrigin: \"https://example.com\",\n                                                 delegate: \"fullscreen\"});\n\n// Sub-frame (\"presentation window\") code\nwindow.onmessage = () =\u003e document.body.requestFullscreen();\n```\n\n### Allowing display capture from cross-origin iframe click\n\nConsider a web app in which you want to add video-conferencing capabilities.\nYou turn to a third party solution that can be embedded in a cross-origin\n`iframe`. There's a lot of logic behind the scenes, but UX-wise, maybe you\nwork out a scheme where it's mostly the video which is user-facing in the\nvideo-conferencing `iframe`, and the user-facing controls - mute, leave,\nshare-screen - are all part of the web app, and receive its specific UX\nstyling. When those buttons are pressed, some messages are exchanged between\nthe web app and the embedded video-conferencing solution.\n\nTo let the third-party `iframe` to prompt the user to share a tab, a window,\nor a screen, the top frame would delegate the `mediaDevices.getDisplayMedia()`\npermission to the `iframe` as follows:\n\n```js\n// In the top frame, user clicks the \"Share My Screen\" button.\nbutton.onclick = () =\u003e\n  frames[0].postMessage(\"msg\", { delegate: \"display-capture\" });\n```\n\n```js\n// In the cross-origin video-conferencing iframe, prompt the user\n// to share a tab, a window, or a screen.\nwindow.onmessage = () =\u003e navigator.mediaDevices.getDisplayMedia();\n```\n\n\n### Other similar scenarios\n\n* A web service that does not care about user location except for a \"branch\n  locator\" functionality provided by a third-party map-provider app can delegate\n  its own location access capability to the map `iframe` in a temporary manner\n  right after the \"branch locator\" button is clicked.\n\n* An authentication provider may wish to show a popup to complete the\n  authentication flow before returning a token to the host site.\n\n* A website may want a third-party chat app in an `iframe` to be able to vibrate\n  the phone on message receipt, even when the user is not active in the\n  `iframe`.\n\n\n## Non-goals\n\n* This explainer is not about delegation of [user\n  activation](https://html.spec.whatwg.org/multipage/interaction.html#tracking-user-activation)\n  (i.e., allowing the `iframe` to choose from all of the things the top frame\n  could do after a user click or other interaction).  See [Considered\n  Alternatives](#considered-alternatives) below for more details.\n\n* This explainer does not determine which APIs could possibly support capability\n  delegation.  If any API needs the support, the designers of the API would\n  decide details of delegated behavior.  The PaymentRequest API case presented\n  here (in collaboration with the owners of that API) serves as a guide for\n  similar changes in other API specifications.\n\n\n## Using capability delegation\n\nDevelopers would use Capability Delegation by just initiating the delegation\nappropriately, as shown in the example code snippets above.  In short, when a\n[browsing\ncontext](https://html.spec.whatwg.org/multipage/browsers.html#browsing-context)\nwants to delegate a capability to another browsing context, it sends a\n`postMessage()` to the second browsing context with an extra\n[`WindowPostMessageOptions`](https://html.spec.whatwg.org/multipage/window-object.html#windowpostmessageoptions)\nmember called `delegate` specifying the capability.\n\nAfter a successful delegation, the \"user API\" (the restricted API being\ndelegated) just works when called at the right moment.  The general idea is\ncalling the restricted API in a `MessageEvent` handler or soon afterwards.  In\nthe examples above, the restricted APIs are `payment_request.show()`,\n`element.requestFullscreen()`, and `mediaDevices.getDisplayMedia()` respectively.\n\n\n### Demo\n\n- Payment Request API: To see how this API works with Payment Request, run\nChrome with the command-line flag: `--enable-blink-features=PaymentRequestRequiresUserActivation`, then open\n[this\ndemo](https://wicg.github.io/capability-delegation/example/payment-request/).\n\n- Fullscreen API: Work in progress.\n\n- Screen Capture API: Work in progress.\n\n## Related links\n\n* [Design\n  discussion](https://docs.google.com/document/d/1IYN0mVy7yi4Afnm2Y0uda0JH8L2KwLgaBqsMVLMYXtk).\n\n\n## Considered alternatives\n\n### Delegating user activation instead of a specific capability\n\nIt may appear that we can delegate user activation to solve the same use-cases\nand thus avoid specifying a feature in the `postMessage()` call.  We attempted\nthis direction in the past from a few different perspectives, and decided not to\npursue this.  In particular, user activation controls many Web APIs, so\ndelegating user activation for any of the mentioned use-cases is impossible\nwithout causing problems with unrelated APIs.  See the [TAG\ndiscussion](https://github.com/w3ctag/design-reviews/issues/347) with one past\nattempt.\n\n\n### Using a delegation-specific method instead of postMessage()\n\nInstead of piggy-backing the delegation request as a `PostMessageOptions` entry,\nwe considered adding a new delegation-specific interface on the `Window` object.\nWhile the latter may look cleaner from a developer’s perspective, to support\ncross-origin communication this solution would require adding the new method on\nthe\n[`WindowProxy`](https://developer.mozilla.org/en-US/docs/Glossary/WindowProxy)\nwrapper, which HTML's editor [strongly\ndisliked](https://github.com/whatwg/html/pull/4369#issuecomment-470580082).\n\n\n## Stakeholder feedback/opposition\n\nWe will track the overall status through this [Chrome Status\nentry](https://www.chromestatus.com/feature/5708770829139968).\n\n\n## Acknowledgements\n\nMany thanks for valuable feedback and advice from:\n\n* Anne van Kesteren ([github.com/annevk](https://github.com/annevk))\n* Jeffrey Yasskin ([github.com/jyasskin](https://github.com/jyasskin))\n* Robert Flack ([github.com/flackr](https://github.com/flackr))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwicg%2Fcapability-delegation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwicg%2Fcapability-delegation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwicg%2Fcapability-delegation/lists"}