Skip to main content

src/plume@permissions_policy.erl

-module(plume@permissions_policy).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/plume/permissions_policy.gleam").
-export([to_string/1]).
-export_type([permissions_policy/0, directive/0, allowlist/0, origin/0]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(
    " Permissions-Policy\n"
    "\n"
    " This response header lets a site declare which\n"
    " browser features the document and any embedded frames are allowed to use.\n"
    " A policy is a comma-separated list of directives, each pairing a feature\n"
    " name with an allowlist of origins that may use it.\n"
    "\n"
    " Each directive has its own browser default when the header is not set —\n"
    " commonly `self`, but some features default to `*`. Omitting a directive\n"
    " defers to whichever default the browser applies. An empty allowlist\n"
    " (`Origins([])`) renders as `()` and disables the feature everywhere.\n"
    "\n"
    " ## Examples\n"
    "\n"
    " ```gleam\n"
    " Policy([\n"
    "   Geolocation(Origins([])),\n"
    "   Camera(Origins([Self])),\n"
    "   Fullscreen(Wildcard),\n"
    " ])\n"
    " ```\n"
    "\n"
    " See the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Permissions-Policy).\n"
).

-type permissions_policy() :: {policy, list(directive())}.

-type directive() :: {accelerometer, allowlist()} |
    {ambient_light_sensor, allowlist()} |
    {aria_notify, allowlist()} |
    {attribution_reporting, allowlist()} |
    {autoplay, allowlist()} |
    {bluetooth, allowlist()} |
    {browsing_topics, allowlist()} |
    {camera, allowlist()} |
    {captured_surface_control, allowlist()} |
    {ch_ua_high_entropy_values, allowlist()} |
    {compute_pressure, allowlist()} |
    {cross_origin_isolated, allowlist()} |
    {deferred_fetch, allowlist()} |
    {deferred_fetch_minimal, allowlist()} |
    {display_capture, allowlist()} |
    {encrypted_media, allowlist()} |
    {fullscreen, allowlist()} |
    {gamepad, allowlist()} |
    {geolocation, allowlist()} |
    {gyroscope, allowlist()} |
    {hid, allowlist()} |
    {identity_credentials_get, allowlist()} |
    {idle_detection, allowlist()} |
    {language_detector, allowlist()} |
    {local_fonts, allowlist()} |
    {magnetometer, allowlist()} |
    {microphone, allowlist()} |
    {midi, allowlist()} |
    {on_device_speech_recognition, allowlist()} |
    {otp_credentials, allowlist()} |
    {payment, allowlist()} |
    {picture_in_picture, allowlist()} |
    {private_state_token_issuance, allowlist()} |
    {private_state_token_redemption, allowlist()} |
    {public_key_credentials_create, allowlist()} |
    {public_key_credentials_get, allowlist()} |
    {screen_wake_lock, allowlist()} |
    {serial, allowlist()} |
    {speaker_selection, allowlist()} |
    {storage_access, allowlist()} |
    {summarizer, allowlist()} |
    {translator, allowlist()} |
    {usb, allowlist()} |
    {web_share, allowlist()} |
    {window_management, allowlist()} |
    {xr_spatial_tracking, allowlist()}.

-type allowlist() :: wildcard | {origins, list(origin())}.

-type origin() :: self | src | {url, binary()}.

-file("src/plume/permissions_policy.gleam", 247).
-spec origin_to_string(origin()) -> binary().
origin_to_string(Origin) ->
    case Origin of
        self ->
            <<"self"/utf8>>;

        src ->
            <<"src"/utf8>>;

        {url, Value} ->
            <<<<"\""/utf8, Value/binary>>/binary, "\""/utf8>>
    end.

-file("src/plume/permissions_policy.gleam", 239).
-spec allowlist_to_string(allowlist()) -> binary().
allowlist_to_string(Allowlist) ->
    case Allowlist of
        wildcard ->
            <<"*"/utf8>>;

        {origins, Origins} ->
            <<<<"("/utf8,
                    (gleam@string:join(
                        gleam@list:map(Origins, fun origin_to_string/1),
                        <<" "/utf8>>
                    ))/binary>>/binary,
                ")"/utf8>>
    end.

-file("src/plume/permissions_policy.gleam", 235).
-spec render_directive(binary(), allowlist()) -> binary().
render_directive(Name, Allowlist) ->
    <<<<Name/binary, "="/utf8>>/binary,
        (allowlist_to_string(Allowlist))/binary>>.

-file("src/plume/permissions_policy.gleam", 166).
-spec directive_to_string(directive()) -> binary().
directive_to_string(Directive) ->
    case Directive of
        {accelerometer, Allowlist} ->
            render_directive(<<"accelerometer"/utf8>>, Allowlist);

        {ambient_light_sensor, Allowlist@1} ->
            render_directive(<<"ambient-light-sensor"/utf8>>, Allowlist@1);

        {aria_notify, Allowlist@2} ->
            render_directive(<<"aria-notify"/utf8>>, Allowlist@2);

        {attribution_reporting, Allowlist@3} ->
            render_directive(<<"attribution-reporting"/utf8>>, Allowlist@3);

        {autoplay, Allowlist@4} ->
            render_directive(<<"autoplay"/utf8>>, Allowlist@4);

        {bluetooth, Allowlist@5} ->
            render_directive(<<"bluetooth"/utf8>>, Allowlist@5);

        {browsing_topics, Allowlist@6} ->
            render_directive(<<"browsing-topics"/utf8>>, Allowlist@6);

        {camera, Allowlist@7} ->
            render_directive(<<"camera"/utf8>>, Allowlist@7);

        {captured_surface_control, Allowlist@8} ->
            render_directive(<<"captured-surface-control"/utf8>>, Allowlist@8);

        {ch_ua_high_entropy_values, Allowlist@9} ->
            render_directive(<<"ch-ua-high-entropy-values"/utf8>>, Allowlist@9);

        {compute_pressure, Allowlist@10} ->
            render_directive(<<"compute-pressure"/utf8>>, Allowlist@10);

        {cross_origin_isolated, Allowlist@11} ->
            render_directive(<<"cross-origin-isolated"/utf8>>, Allowlist@11);

        {deferred_fetch, Allowlist@12} ->
            render_directive(<<"deferred-fetch"/utf8>>, Allowlist@12);

        {deferred_fetch_minimal, Allowlist@13} ->
            render_directive(<<"deferred-fetch-minimal"/utf8>>, Allowlist@13);

        {display_capture, Allowlist@14} ->
            render_directive(<<"display-capture"/utf8>>, Allowlist@14);

        {encrypted_media, Allowlist@15} ->
            render_directive(<<"encrypted-media"/utf8>>, Allowlist@15);

        {fullscreen, Allowlist@16} ->
            render_directive(<<"fullscreen"/utf8>>, Allowlist@16);

        {gamepad, Allowlist@17} ->
            render_directive(<<"gamepad"/utf8>>, Allowlist@17);

        {geolocation, Allowlist@18} ->
            render_directive(<<"geolocation"/utf8>>, Allowlist@18);

        {gyroscope, Allowlist@19} ->
            render_directive(<<"gyroscope"/utf8>>, Allowlist@19);

        {hid, Allowlist@20} ->
            render_directive(<<"hid"/utf8>>, Allowlist@20);

        {identity_credentials_get, Allowlist@21} ->
            render_directive(<<"identity-credentials-get"/utf8>>, Allowlist@21);

        {idle_detection, Allowlist@22} ->
            render_directive(<<"idle-detection"/utf8>>, Allowlist@22);

        {language_detector, Allowlist@23} ->
            render_directive(<<"language-detector"/utf8>>, Allowlist@23);

        {local_fonts, Allowlist@24} ->
            render_directive(<<"local-fonts"/utf8>>, Allowlist@24);

        {magnetometer, Allowlist@25} ->
            render_directive(<<"magnetometer"/utf8>>, Allowlist@25);

        {microphone, Allowlist@26} ->
            render_directive(<<"microphone"/utf8>>, Allowlist@26);

        {midi, Allowlist@27} ->
            render_directive(<<"midi"/utf8>>, Allowlist@27);

        {on_device_speech_recognition, Allowlist@28} ->
            render_directive(
                <<"on-device-speech-recognition"/utf8>>,
                Allowlist@28
            );

        {otp_credentials, Allowlist@29} ->
            render_directive(<<"otp-credentials"/utf8>>, Allowlist@29);

        {payment, Allowlist@30} ->
            render_directive(<<"payment"/utf8>>, Allowlist@30);

        {picture_in_picture, Allowlist@31} ->
            render_directive(<<"picture-in-picture"/utf8>>, Allowlist@31);

        {private_state_token_issuance, Allowlist@32} ->
            render_directive(
                <<"private-state-token-issuance"/utf8>>,
                Allowlist@32
            );

        {private_state_token_redemption, Allowlist@33} ->
            render_directive(
                <<"private-state-token-redemption"/utf8>>,
                Allowlist@33
            );

        {public_key_credentials_create, Allowlist@34} ->
            render_directive(
                <<"publickey-credentials-create"/utf8>>,
                Allowlist@34
            );

        {public_key_credentials_get, Allowlist@35} ->
            render_directive(<<"publickey-credentials-get"/utf8>>, Allowlist@35);

        {screen_wake_lock, Allowlist@36} ->
            render_directive(<<"screen-wake-lock"/utf8>>, Allowlist@36);

        {serial, Allowlist@37} ->
            render_directive(<<"serial"/utf8>>, Allowlist@37);

        {speaker_selection, Allowlist@38} ->
            render_directive(<<"speaker-selection"/utf8>>, Allowlist@38);

        {storage_access, Allowlist@39} ->
            render_directive(<<"storage-access"/utf8>>, Allowlist@39);

        {summarizer, Allowlist@40} ->
            render_directive(<<"summarizer"/utf8>>, Allowlist@40);

        {translator, Allowlist@41} ->
            render_directive(<<"translator"/utf8>>, Allowlist@41);

        {usb, Allowlist@42} ->
            render_directive(<<"usb"/utf8>>, Allowlist@42);

        {web_share, Allowlist@43} ->
            render_directive(<<"web-share"/utf8>>, Allowlist@43);

        {window_management, Allowlist@44} ->
            render_directive(<<"window-management"/utf8>>, Allowlist@44);

        {xr_spatial_tracking, Allowlist@45} ->
            render_directive(<<"xr-spatial-tracking"/utf8>>, Allowlist@45)
    end.

-file("src/plume/permissions_policy.gleam", 159).
?DOC(" Encode as the `Permissions-Policy` header value.\n").
-spec to_string(permissions_policy()) -> binary().
to_string(Value) ->
    {policy, Directives} = Value,
    _pipe = Directives,
    _pipe@1 = gleam@list:map(_pipe, fun directive_to_string/1),
    gleam@string:join(_pipe@1, <<", "/utf8>>).