Powerful browser features such as the camera, microphone, geolocation, payment requests, USB and fullscreen are controlled per document. Permissions Policy lets you switch them off for your own page and decide which embedded frames may even ask for them. It limits what compromised or third-party code can do: an ad frame that is denied geolocation cannot trigger a location prompt, however it is written. The mechanism was introduced as Feature Policy with a Feature-Policy header; it was renamed, and the header syntax changed to structured fields.
The old Feature-Policy: camera 'none'; geolocation 'self' https://maps.example is written today as Permissions-Policy: camera=(), geolocation=(self "https://maps.example"). In the header, * allows every origin, () disables the feature everywhere, self means the page's own origin, and other origins appear in double quotes. Frames need a second grant through the allow attribute, whose syntax is the old one: unquoted origins, keywords in single quotes, default 'src' (the frame's own origin). A cross-origin frame can use a feature only if both the top-level policy and its allow list permit it.
<!-- Page served with: Permissions-Policy: geolocation=(self "https://maps.example"), camera=() -->
<iframe src="https://maps.example/embed" allow="geolocation" title="Store locator"></iframe>
<!-- Asking for the camera fails: the page's header disabled it everywhere -->
<iframe src="https://chat.example/widget" allow="camera; microphone" title="Support chat"></iframe>Support differs between the two halves. The Permissions-Policy header is implemented only in Chromium-based browsers (Chrome 88 1 onward for most features); Firefox 555 and Safari 10 ignore it. The allow attribute works in all engines for the features each one implements (Chrome 60, Firefox 74, Safari 11.1). Append ;report-to=endpoint to a directive to receive violation reports through the Reporting API.