v152 · chromeos · isolated web apps · enabled by default
Window Shape API
window.chromeos.isolatedWebApp.setShape() lets an allowlisted Isolated Web App (IWA) on ChromeOS set the visible and interactive shape of its window to the union of a list of rectangles — enabling non-rectangular and non-contiguous window layouts such as widgets, floating panels, and overlays.
This API is a Blink extension for Chrome on ChromeOS, exposed only to allowlisted Isolated Web Apps. It is not on any standardization track and is not available to ordinary web pages, tabs, or PWAs. The chromeos.isolatedWebApp.* namespace exists precisely to signal that (the same pattern as Android WebView’s window.android.webview.* extensions), and it survived an explicit API-review debate on that basis — see why it exists.
- Listing status. The Chrome 152 milestone listing files this feature under both “Enabled by default” and “Stepped rollout” (milestone=152 listing, verified 2026-07-28; the listing is authoritative for identity).
- Runtime flag. The Blink runtime feature is
BlinkExtensionChromeOSIsolatedWebAppSetShape, status{"ChromeOS": "experimental", "default": ""}— at trunk and on the M152 branch (both fetched 2026-07-28). Enablement for allowlisted IWAs is brokered by the browser process (browser_process_read_write_access: true, depends onBlinkExtensionChromeOS), which is how an “experimental” Blink status coexists with the “Enabled by default” listing for the allowlisted population. For local development outside the allowlist, enablechrome://flags/#enable-chromeos-isolated-web-app-set-shape(flag name per the Intent to Ship). - Prerequisites. The calling context must be (1) an IWA whose origin is on the ChromeOS allowlist, (2) running in the
unframeddisplay mode, and (3) granted thewindow-managementpermission.
at a glance
| What it is | A single method, IsolatedWebApp.setShape(rects), that masks the OS window to the union of up to 10,000 rectangles; plus the two namespace attributes that expose it (Window.chromeos, ChromeOS.isolatedWebApp) |
|---|---|
| Ships in | Chrome 152, desktop ChromeOS only — the milestone=152 listing files it under “Enabled by default” and “Stepped rollout” (verified 2026-07-28); the ChromeStatus record lists desktop 152 with no Android/WebView/iOS milestones |
| Audience | Allowlisted Isolated Web Apps on ChromeOS only — currently a small set of VDI partners migrating from deprecated Chrome Apps (explainer: “the allowlist will remain small”) |
| Predecessor | Mirrors the Chrome Apps chrome.app.window.setShape([rects]) API for signature and behavior parity |
| Prerequisites | Allowlisted IWA origin · unframed display mode · window-management permission |
| Runtime feature | BlinkExtensionChromeOSIsolatedWebAppSetShape (ChromeOS experimental, browser-process-gated; depends on BlinkExtensionChromeOS) |
| WPT | None — the Intent to Ship answers “Is this feature fully tested by web-platform-tests?” with “No”, and no chromeos/isolated-web-app/window-shape directory exists in the WPT repository (verified 2026-07-28) |
| ChromeStatus | 5075144470036480 — Window Shape API (blink component UI>Browser>WebAppInstalls>Isolated) |
why it exists
Chrome Apps are deprecated. Virtual Desktop Infrastructure (VDI) partners that built Chrome Apps are migrating to Isolated Web Apps, and they need capabilities the standard web platform does not offer — among them custom window shapes for floating overlays and widgets. Chrome Apps provided this through chrome.app.window.setShape([rects]); the Window Shape API ports that exact capability — same signature shape, same rectangle-union behavior — so partners can migrate with minimal changes to their window-management logic.
The Chrome team is explicit that this is not a candidate for the interoperable web: the explainer argues the VDI use cases are better served long-term by more specific APIs (for example, a dedicated floating-window API) than by general window-shape masking, and the allowlist exists to prevent widespread adoption of an API with no standardization path. The intent thread records the debate: Alex Russell objected to baking a chromeos namespace and this masking model into the platform and marked the entry “needs work”; the owners resolved it by documenting scope considerations and alternatives in the explainer, and the feature shipped with LGTM1 (Chris Harrelson), LGTM2 (Mike Taylor), and an IWA-owner LGTM (Reilly Grant) on the basis that a Blink extension visible only to allowlisted IWAs “doesn’t set a new precedent”.
API entry points
All ChromeOS-specific web APIs hang off a single namespace attribute on Window. The full interface chain (verbatim from the specification):
partial interface Window {
[Replaceable] readonly attribute ChromeOS chromeos;
};
[Exposed=Window]
interface ChromeOS {
readonly attribute IsolatedWebApp isolatedWebApp;
};
[Exposed=Window]
interface IsolatedWebApp {};
// Window Shape API extension:
partial interface IsolatedWebApp {
Promise<undefined> setShape(sequence<DOMRectReadOnly> rects);
};
Source: spec §2 API Entry Points; spec §3.3 API Extension.
Window.chromeos
| Syntax | [Replaceable] readonly attribute ChromeOS chromeos; — accessed as window.chromeos. [Replaceable] means assigning to window.chromeos shadows the accessor with an own property (WebIDL semantics). |
|---|---|
| Returns | The ChromeOS namespace object, or null “if the current context is not allowlisted to use any of ChromeOS IWA APIs” (spec §2.1). In practice that means null for every ordinary web page, tab, PWA, and non-allowlisted IWA. |
| Context & exposure | [Exposed=Window] — window contexts only, not workers. ChromeOS-only Blink extension; attribute is absent (or null) on all other platforms. Feature-detect with optional chaining: window.chromeos?.isolatedWebApp. |
| Lifecycle | Read at any time; the value does not change for the lifetime of the window. Allowlist evaluation happens at context creation — there is no runtime “became allowlisted” transition to observe. |
| Errors | No exception surface: a non-allowlisted context receives null rather than a thrown error. Dereferencing window.chromeos.isolatedWebApp without a null check throws the page’s own TypeError. |
| Example | const iwa = window.chromeos?.isolatedWebApp; (see examples) |
| Compatibility | Chrome on ChromeOS only, from 152, allowlisted contexts; undefined everywhere else (see browser compatibility). |
| Security & privacy | Presence of a non-null value reveals that the context is an allowlisted IWA on ChromeOS — information the app already has about itself; no cross-context disclosure (see security and privacy). |
ChromeOS.isolatedWebApp
| Syntax | readonly attribute IsolatedWebApp isolatedWebApp; — accessed as window.chromeos.isolatedWebApp. |
|---|---|
| Returns | The IsolatedWebApp object (the host of setShape()), or null “if the current context is not an IWA or not allowlisted to use the ChromeOS IWA APIs” (spec §2.2). |
| Context & exposure | Only meaningful inside an Isolated Web App running on ChromeOS; requires the origin to be allowlisted. The IsolatedWebApp interface itself is [Exposed=Window]. |
| Lifecycle | Stable for the lifetime of the window; no events fire on it. |
| Errors | No exception surface — unavailable contexts receive null. |
| Example | if (iwa && typeof iwa.setShape === "function") { … } (see examples) |
| Compatibility | Chrome on ChromeOS only, from 152, allowlisted IWAs (see browser compatibility). |
| Security & privacy | The sub-namespace makes the IWA-only restriction explicit so standard web content can never reach the capability (see security and privacy). |
Syntax
The feature adds one method to the IsolatedWebApp interface (full reference: setShape()):
partial interface IsolatedWebApp {
Promise<undefined> setShape(sequence<DOMRectReadOnly> rects);
};
rects is a list of rectangles in Device Independent Pixels (DIPs) in the local coordinate space of the OS window. The window’s visible and interactive area becomes the union of those rectangles — anything outside every rectangle is not rendered and cannot be clicked. Passing an empty array resets the window to its default rectangular shape.
coordinate space and scaling
| Units | Device Independent Pixels (DIPs), in the OS window’s local coordinate space. At 100% page zoom, 1 DIP equals 1 CSS pixel. |
|---|---|
| Fractional values | DOMRectReadOnly accepts floating-point x/y/width/height, but OS shape primitives work on integer boundaries: values are truncated to integers and clamped to the 32-bit signed integer range when the shape is applied. |
| Device pixel ratio | On high-density displays (devicePixelRatio ≠ 1), the window compositor automatically scales DIP coordinates by the display’s device scale factor. No manual scaling by the developer. |
| Page zoom | Coordinates are window DIPs, not document CSS pixels, so page zoom does not scale the window shape. Recompute and re-call setShape() on zoom changes only if the shape should track zoomed content. |
Examples
Set a two-rectangle overlapping shape, then reset it (the explainer’s canonical example):
// Set a window shape consisting of two overlapping rectangles.
await window.chromeos.isolatedWebApp.setShape([
new DOMRect(0, 0, 200, 200),
new DOMRect(180, 190, 100, 300),
]);
// Clear the custom shape (reset to default rectangular window).
await window.chromeos.isolatedWebApp.setShape([]);
Feature detection and guarded call (the pattern used by the official demo IWA):
const iwa = window.chromeos?.isolatedWebApp;
if (iwa && typeof iwa.setShape === "function") {
try {
await iwa.setShape(shapeRects);
} catch (e) {
console.error("setShape error:", e);
}
} else {
// Not an allowlisted IWA on ChromeOS — hide shape-dependent UI.
}
setShape() (route HEAD-checked 200, 2026-07-28).Source: chrome-platform-showcase — rectangle composer.A complete, installable IWA demonstrating setShape with the Window Management API — including the out-of-bounds popups/tooltips pattern and a static-vs-dynamic buffer toggle — is maintained at github.com/paulinagacek/Set-Shape-demo; its TypeScript declarations match the specification IDL above.
web platform tests
There is no WPT coverage for this API. The Intent to Ship answers “Is this feature fully tested by web-platform-tests?” with “No”, and no chromeos/, isolated-web-app/, or window-shape/ directory exists in the web-platform-tests repository (repository tree checked 2026-07-28). This is consistent with the feature’s positioning: a ChromeOS-only Blink extension with no cross-browser interoperability goal.
browser compatibility
Interim table. There is no BCD entry (BCD api/Window.json contains no chromeos member, verified 2026-07-28) and no web-features entry (webstatus.dev query, zero matches). Rows below are compiled from the linked primary sources, not from BCD.
| Browser | Support | Evidence |
|---|---|---|
| Chrome (ChromeOS) | 152+, allowlisted IWAs only | milestone=152 listing (“Enabled by default” and “Stepped rollout”); Intent to Ship (“Shipping on desktop 152”) |
| Chrome (Windows, macOS, Linux, Android, WebView) | Not available | Intent to Ship: “implemented as a Blink extension for Chrome on ChromeOS. It will not be available in any other platform” |
| Edge | Not available | Chromium-based but not ChromeOS; the Blink extension is ChromeOS-only (explainer) |
| Firefox | No signal | ChromeStatus record vendor views; intent: “not meant to be implemented by other browsers” |
| Safari | No signal | ChromeStatus record vendor views |
security and privacy
- Invisible or tiny windows. A shaped window could be made effectively hidden to act without the user’s knowledge. Mitigation: every shape must contain at least one rectangle of at least 10×10 DIPs; smaller rectangles alone are rejected (see exceptions).
- Clickjacking by occlusion. A shaped (for example donut-shaped) window can partially occlude another application and trick users into clicking the wrong UI. Mitigations: allowlist restriction and the required
window-managementpermission grant. - Allowlist as the primary boundary. Only vetted origins can call the API at all —
window.chromeosisnulleverywhere else — so ordinary web content has no path to the capability. Enterprise administrators can further control availability with the existing window-management policies DefaultWindowManagementSetting, WindowManagementAllowedForUrls, and WindowManagementBlockedForUrls (the last forces removal of any custom shape and fallback to another display mode). - No standardization surface. The
chromeos.isolatedWebAppnamespace deliberately signals embedder-specific, non-standard API so it cannot be mistaken for (or become) a web-platform contract.
specifications
| Document | Status |
|---|---|
| ChromeOS APIs for Isolated Web Apps | Informative, vendor-published specification (bikeshed). The normative reference for the entry points and the setShape() algorithm. Not on a W3C/WHATWG standardization track — intentionally. |
| Window Shape API explainer | Motivation, scope considerations, security analysis, alternatives considered |
WICG Manifest Incubations — unframed display mode | Prerequisite display mode; user agents MUST restrict unframed to IWAs, and the display mode is fixed for the window’s lifetime |
Geometry Interfaces — DOMRectReadOnly | Input rectangle type (W3C Recommendation) |
| Window Management API | The window-management permission the API requires |
see also
IsolatedWebApp.setShape()reference — parameters, validation, exceptions, and the full application algorithm- Unframed display mode for Isolated Web Apps — the sibling Chrome 152 feature that is a prerequisite for this API
- Chrome Platform Status — Window Shape API (API record)
- blink-dev — Intent to Ship: Window shape API
- Set-Shape-demo — official demo IWA (TypeScript)
- chromeos.dev — Isolated Web Apps
- Chrome Platform Showcase — interactive demos for this feature