Permission Policy Test Page

Tests how the web-app-installation Permissions Policy affects navigator.install() and the <install> element in various iframe configurations.

← Back to main test page

How Permissions Policy works:

1. Top-level page (control)

These run directly in the top-level browsing context. Should always work.

navigator.install() — 0 params (install self)

await navigator.install();

<install> element — current page

<install></install>

2. Same-origin iframes

2a. Same-origin iframe — NO allow attribute (default)

Expected: Blocked — subframes do not inherit the permission by default.

<iframe src="iframe.html"></iframe>

2b. Same-origin iframe — WITH allow="web-app-installation"

Expected (with iframe support): Allowed — parent explicitly delegates the permission to same-origin child.

Expected (without iframe support): Blocked — delegation not supported.

<iframe src="iframe.html" allow="web-app-installation"></iframe>

2c. Same-origin iframe — allow="web-app-installation 'none'" (explicitly denied)

Expected: Blocked — parent explicitly revokes the permission even for same-origin.

<iframe src="iframe.html" allow="web-app-installation 'none'"></iframe>

2d. Same-origin iframe — allow="web-app-installation 'self'"

Expected (with iframe support): Allowed — explicitly grants to self (the iframe's own origin, which matches the parent).

Expected (without iframe support): Blocked — delegation not supported.

<iframe src="iframe.html" allow="web-app-installation 'self'"></iframe>

3. Cross-origin iframes

3a. Cross-origin iframe — NO allow attribute

Expected: Blocked — cross-origin without delegation.

<iframe src="https://liahiscock.github.io/PWA/WebInstall/index.html"></iframe>

3b. Cross-origin iframe — WITH allow="web-app-installation"

Expected: Delegation attempted — behavior depends on whether cross-origin install delegation is supported.

<iframe src="https://liahiscock.github.io/PWA/WebInstall/index.html" allow="web-app-installation"></iframe>

3c. Cross-origin iframe — allow="web-app-installation https://liahiscock.github.io"

Expected: Delegation to specific origin — tests origin-scoped delegation.

<iframe src="https://liahiscock.github.io/PWA/WebInstall/index.html" allow="web-app-installation https://liahiscock.github.io"></iframe>

4. Sandboxed iframes

4a. Sandboxed iframe — sandbox="allow-scripts", no allow

Expected: Blocked — not supported.

<iframe src="iframe.html" sandbox="allow-scripts"></iframe>

4b. Sandboxed iframe — sandbox="allow-scripts" + allow="web-app-installation"

Expected: Blocked — not supported.

<iframe src="iframe.html" sandbox="allow-scripts" allow="web-app-installation"></iframe>

4c. Sandboxed iframe — sandbox="allow-scripts allow-same-origin" + allow="web-app-installation"

Expected: Blocked — not supported.

<iframe src="iframe.html" sandbox="allow-scripts allow-same-origin" allow="web-app-installation"></iframe>

5. <install> element in iframes

The <install> element should obey the same permission policy as the API.

5a. Same-origin iframe with <install> — no allow

Expected: Blocked

5b. Same-origin iframe with <install> — WITH allow="web-app-installation"

Expected (with iframe support): Allowed

Expected (without iframe support): Blocked

<iframe src="iframe.html" allow="web-app-installation"></iframe>

5c. Cross-origin iframe with <install> — WITH allow="web-app-installation"

Expected: Delegation attempted — depends on cross-origin support.

6. Permissions-Policy HTTP header (informational)

The Permissions-Policy HTTP response header can also control the policy at the server level. Examples:


// Disable for all contexts (including self):
Permissions-Policy: web-app-installation=()

// Allow for self only (default):
Permissions-Policy: web-app-installation=(self)

// Allow for self and a specific origin:
Permissions-Policy: web-app-installation=(self "https://liahiscock.github.io")

// Allow for all origins:
Permissions-Policy: web-app-installation=*
    

Note: GitHub Pages does not support custom HTTP response headers. To test header-based policies, you would need a server you control (e.g., Express, Netlify with _headers, Cloudflare Workers, or a local dev server).