v157 · capabilities · the full flow, for real
Notification → popup lab
The explainer's webmail scenario, live: a service-worker notification whose click makes this already-open tab open a connected preview popup. Every stage below is the real API — real registration, real permission prompt, real notification, real client.postMessage(…, {delegate: 'popup'}) in the worker, and a real synchronous window.open() in this page's message handler. On a browser without the feature, that last call hits the popup blocker — which is precisely the gap being closed, and this lab shows it honestly.
To see the delegated success path you need a Chromium build with the CapabilityDelegationPopup flag — launch with --enable-experimental-web-platform-features (no released Chrome ships it; ChromeStatus milestone: none yet). Everywhere else, stages 1–5 still run for real and stage 6 reports the genuine popup-blocker outcome. Notifications also require this page to stay visible/focused when you click the notification.
The flow
- waiting1 · Register the service worker (../sw.js, feature scope)
- waiting2 · Notification permission
- waiting3 · Show the notification (then click it!)
- waiting4 · Worker receives notificationclick, focuses this tab, posts the message
- waiting5 · This page receives the message
- waiting6 · window.open() from the message handler
Nothing yet.
what the popup proves
The popup this lab opens is popup-target.html. It checks window.opener, synchronously reads a value this tab holds in memory (LAB_SHARED_STATE) and messages back — the state-sharing that Clients.openWindow()'s cold new context cannot give you, and the reason the explainer routes the open through the client tab instead of the worker.