Um teste de origem para um novo elemento HTML <permissão>

Há vários métodos imperativos para solicitar permissão para usar recursos avançados, como o acesso à localização em apps da Web. Esses métodos apresentam vários desafios, e é por isso que a equipe de permissões do Chrome está testando um novo método declarativo: um elemento <permission> HTML dedicado. Esse elemento está em teste de origem no Chrome 126, e esperamos padronizá-lo.

Métodos imperativos para solicitar permissões

Quando os apps da Web precisam de acesso a recursos avançados, eles precisam pedir permissão. Por exemplo, quando o Google Maps exige a localização do usuário usando a API Geolocation, os navegadores solicitam a permissão do usuário, geralmente com a opção de armazenar essa decisão. Esse é um conceito bem definido na especificação de permissões.

Perguntar implicitamente no primeiro uso em vez de solicitar explicitamente

A API Geolocation é uma API poderosa e depende da abordagem de solicitação implícita no primeiro uso. Por exemplo, quando um app chama o método navigator.geolocation.getCurrentPosition(), a solicitação de permissão aparece automaticamente na primeira chamada. Outro exemplo é navigator.mediaDevices.getUserMedia().

Outras APIs, como a API Notification ou a API Device Orientation and Motion, geralmente têm uma maneira explícita de solicitar permissão usando um método estático, como Notification.requestPermission() ou DeviceMotionEvent.requestPermission().

Desafios com métodos imperativos para solicitar permissão

Spam de permissão

Antes, os sites podiam chamar métodos como navigator.mediaDevices.getUserMedia() ou Notification.requestPermission(), mas também navigator.geolocation.getCurrentPosition() imediatamente quando um site era carregado. Uma solicitação de permissão aparecia antes que o usuário interagisse com o site. Isso às vezes é descrito como spam de permissão e afeta as duas abordagens, solicitando implicitamente o primeiro uso e explicitamente com antecedência.

Solicitação de permissão do microfone mostrada ao carregar um site.

Mitigações do navegador e requisito de gesto do usuário

O spam de permissões levou os fornecedores de navegadores a exigir um gesto do usuário, como um clique no botão ou um evento de pressionamento de tecla, antes de mostrar um aviso de permissão. O problema com essa abordagem é que é muito difícil, senão impossível, para o navegador descobrir se um determinado gesto do usuário deve resultar na exibição ou não de uma solicitação de permissão. Talvez o usuário tenha clicado na página por frustração porque ela demorou muito para carregar ou talvez ele tenha clicado no botão Localizar. Alguns sites também se tornaram muito bons em enganar os usuários para que cliquem no conteúdo para acionar o comando.

Outra mitigação é adicionar mitigações de abuso de prompts, como bloquear completamente os recursos para começar ou mostrar o prompt de permissão de uma maneira não modal e menos invasiva.

Navegador Chrome mostrando um

Contextualização de permissões

Outro desafio, especialmente em telas grandes, é a forma como o comando de permissão é normalmente exibido: acima da linha da morte, ou seja, fora da área da janela do navegador em que o app pode ser exibido. Não é incomum que os usuários percam o comando na parte de cima da janela do navegador quando clicam em um botão na parte de baixo da janela. Esse problema é agravado quando as mitigações de spam do navegador estão em vigor.

Google Maps com a solicitação de permissão de localização aberta. O botão de acesso à localização que acionou a solicitação está longe.

Não é fácil desfazer

Por fim, é muito fácil para os usuários se perderem. Por exemplo, depois que o usuário bloqueia o acesso a um recurso, ele precisa conhecer o menu suspenso de informações do site, em que é possível redefinir permissões ou reativar as permissões bloqueadas. No pior dos casos, as duas opções exigem uma atualização completa da página até que a configuração atualizada entre em vigor. Os sites não podem oferecer um atalho fácil para que os usuários mudem um estado de permissão existente e precisam explicar detalhadamente como mudar as configurações, conforme mostrado na parte de baixo da captura de tela do Google Maps abaixo.

Controles de site do Chrome no Google Maps para revogar permissões.

Se a permissão for fundamental para a experiência, por exemplo, o acesso de um aplicativo de videoconferência ao microfone, apps como o Google Meet vão mostrar caixas de diálogo intrusivas que orientam o usuário a desbloquear a permissão.

Instruções do Google Meet sobre como abrir os controles do site do Chrome.

Um elemento <permission> declarativo

Para resolver os desafios descritos nesta postagem, a equipe de permissões do Chrome lançou um teste de origem para um novo elemento HTML, <permission>. Esse elemento permite que os desenvolvedores peçam permissão de forma declarativa para usar, por enquanto, um subconjunto dos recursos avançados disponíveis para sites. Na forma mais simples, use-a como no exemplo a seguir:

<permission type="camera" />

Ainda está sendo ativamente debatido se <permission> precisa ser um elemento vazio ou não. Um elemento void é um elemento autocontido em HTML que não pode ter nós filhos, o que significa que ele não pode ter uma tag de fim.

O atributo type

O atributo type contém uma lista separada por espaços das permissões que você está solicitando. No momento em que este artigo foi escrito, os valores permitidos eram 'camera', 'microphone' e camera microphone (separados por espaço). Por padrão, esse elemento é renderizado de forma semelhante a botões com o estilo de user agent barebones.

Vários botões de elemento de permissão com câmera, microfone e câmera e microfone.

O atributo type-ext

Para algumas permissões que permitem parâmetros adicionais, o atributo type-ext aceita pares de chave-valor separados por espaços, como, por exemplo, precise:true para a permissão de geolocalização.

O atributo lang

O texto do botão é fornecido pelo navegador e tem como objetivo ser consistente. Portanto, ele não pode ser personalizado diretamente. O navegador muda o idioma do texto com base no idioma herdado do documento ou da cadeia de elementos pai ou um atributo lang opcional. Isso significa que os desenvolvedores não precisam localizar o elemento <permission>. Se o elemento <permission> passar do estágio de teste de origem, várias strings ou ícones poderão ser compatíveis com cada tipo de permissão para aumentar a flexibilidade. Se você tem interesse em usar o elemento <permission> e precisa de uma string ou um ícone específico, entre em contato.

Comportamento

Quando o usuário interage com o elemento <permission>, ele pode passar por vários estágios:

  • Se o usuário não tiver permitido um recurso antes, ele poderá permitir o recurso em todas as visitas ou permitir o recurso na visita atual.

    Solicitação de permissão para permitir um recurso desta vez ou em todas as visitas.

  • Se eles permitiram o recurso antes, podem continuar permitindo ou desativá-lo.

    Solicitação de permissão para continuar permitindo ou parar de permitir.

  • Se eles já haviam proibido um recurso, podem continuar não permitindo ou permitir dessa vez.

    Solicitação de permissão para continuar sem permitir ou permitir desta vez.

O texto do elemento <permission> é atualizado automaticamente com base no status. Por exemplo, se foi concedida permissão para usar um recurso, o texto muda para informar que o recurso é permitido. Se a permissão precisar ser concedida primeiro, o texto será alterado para convidar o usuário a usar o recurso. Compare a captura de tela anterior com a captura de tela a seguir para conferir os dois estados.

Botões de permissão com os textos

Design de CSS

Para garantir que os usuários reconheçam facilmente o botão como uma plataforma para acessar recursos poderosos, o estilo do elemento <permission> é restrito. Se as restrições de estilo não funcionarem para seu caso de uso, gostaríamos de saber como e por que. Embora nem todas as necessidades de estilo possam ser atendidas, esperamos descobrir maneiras seguras de permitir mais estilos para o elemento <permission> após o teste de origem. A tabela a seguir detalha algumas propriedades que têm restrições ou regras especiais aplicadas a elas. Caso alguma das regras seja violada, o elemento <permission> será desativado e não será possível interagir com ele. Qualquer tentativa de interagir com ele resultará em exceções que podem ser capturadas com o JavaScript. A mensagem de erro vai conter mais detalhes sobre a violação detectada.

Propriedade Regras

color, background-color

Pode ser usado para definir a cor do texto e do plano de fundo, respectivamente. O contraste entre as duas cores precisa ser suficiente para que o texto seja claramente legível (taxa de contraste de pelo menos 3). O canal Alfa precisa ser 1.

font-size, zoom

Precisa ser definido no equivalente de small e xxxlarge. Caso contrário, o elemento será desativado. O zoom será considerado ao calcular font-size.

outline-offset

Os valores negativos serão corrigidos para 0.
margin (tudo) Os valores negativos serão corrigidos para 0.

font-weight

Os valores abaixo de 200 serão corrigidos para 200.

font-style

Valores diferentes de normal e italic serão corrigidos para normal.

word-spacing

Valores acima de 0.5em serão corrigidos para 0.5em. Os valores abaixo de 0 serão corrigidos para 0.

display

Valores diferentes de inline-block e none serão corrigidos para inline-block.

letter-spacing

Valores acima de 0.2em serão corrigidos para 0.2em. Os valores abaixo de -0.05em serão corrigidos para -0.05em.

min-height

Vai ter um valor padrão de 1em. Se fornecido, o valor máximo calculado entre o padrão e os valores fornecidos será considerado.

max-height

Vai ter um valor padrão de 3em. Se fornecido, o valor mínimo calculado entre o padrão e os valores fornecidos será considerado.

min-width

Vai ter um valor padrão de fit-content. Se fornecido, o valor máximo calculado entre o padrão e os valores fornecidos será considerado.

max-width

Vai ter um valor padrão de três vezes fit-content. Se forem fornecidos, o valor mínimo calculado entre o padrão e os valores fornecidos será considerado.

padding-top

Só vai entrar em vigor se height estiver definido como auto. Nesse caso, os valores acima de 1em serão corrigidos para 1em, e padding-bottom será definido como o valor de padding-top.

padding-left

Só vai entrar em vigor se width estiver definido como auto. Nesse caso, os valores acima de 5em serão corrigidos para 5em e padding-right será definido como o valor de padding-left..

transform

Não é permitido distorcer efeitos visuais. Por enquanto, só aceitamos tradução 2D e aumento proporcional.

As propriedades CSS a seguir podem ser usadas normalmente:

  • font-kerning
  • font-optical-sizing
  • font-stretch
  • font-synthesis-weight
  • font-synthesis-style
  • font-synthesis-small-caps
  • font-feature-settings
  • forced-color-adjust
  • text-rendering
  • align-self
  • anchor-name aspect-ratio
  • border (e todas as border-* propriedades)
  • clear
  • color-scheme
  • contain
  • contain-intrinsic-width
  • contain-intrinsic-height
  • container-name
  • container-type
  • counter-*
  • flex-*
  • float
  • height
  • isolation
  • justify-self
  • left
  • order
  • orphans
  • outline-* (com a exceção indicada anteriormente para outline-offset)
  • overflow-anchor
  • overscroll-behavior-*
  • page
  • position
  • position-anchor
  • content-visibility
  • right
  • scroll-margin-*
  • scroll-padding-*
  • text-spacing-trim
  • top
  • visibility
  • x
  • y
  • ruby-position
  • user-select
  • width
  • will-change
  • z-index

Além disso, todas as propriedades logicamente equivalentes podem ser usadas (por exemplo, inline-size é equivalente a width), seguindo as mesmas regras que as equivalentes.

Pseudoclasses

Há duas pseudoclasses especiais que permitem estilizar o elemento <permission> com base no estado:

  • :granted: a pseudoclasse :granted permite estilos especiais quando uma permissão foi concedida.
  • :invalid: a pseudoclasse :invalid permite estilos especiais quando o elemento está em um estado inválido, por exemplo, quando ele é veiculado em um iframe de origem cruzada.
permission {
  background-color: green;
}

permission:granted {
  background-color: light-green;
}

/* Not supported during the origin trial. */
permission:invalid {
  background-color: gray;
}

Eventos JavaScript

O elemento <permission> deve ser usado com a API Permissions. Há vários eventos que podem ser detectados:

  • onpromptdismiss: esse evento é acionado quando a solicitação de permissão acionada pelo elemento é dispensada pelo usuário (por exemplo, clicando no botão de fechamento ou clicando fora da solicitação).

  • onpromptaction: esse evento é acionado quando a solicitação de permissão acionada pelo elemento é resolvida pelo usuário ao realizar alguma ação na solicitação em si. Isso não significa necessariamente que o estado da permissão mudou. O usuário pode ter realizado uma ação que mantém o status quo, como continuar para permitir uma permissão.

  • onvalidationstatuschange: esse evento é acionado quando o elemento muda de "valid" para "invalid". O elemento é considerado "valid" quando o navegador confia na integridade do indicador se o usuário clica nele. Caso contrário, é considerado "invalid", por exemplo, quando o elemento é parcialmente ocultado por outro conteúdo HTML.

É possível registrar listeners de eventos para esses eventos diretamente inline no código HTML (<permission type="…" onpromptdismiss="alert('The prompt was dismissed');" />) ou usando addEventListener() no elemento <permission>, conforme mostrado no exemplo abaixo.

<permission type="camera" />
<script>
  const permission = document.querySelector('permission');
  permission.addEventListener('promptdismiss', showCameraWarning);

  function showCameraWarning() {
    // Show warning that the app isn't fully usable
    // unless the camera permission is granted.
  }

  const permissionStatus = await navigator.permissions.query({name: "camera"});
  
  permissionStatus.addEventListener('change', () => {
    // Run the check when the status changes.
    if (permissionStatus.state === "granted") {
      useCamera();
    }
  });

  // Run the initial check.
  if (permissionStatus.state === "granted") {
    useCamera();
  }
</script>

Detecção de recursos

Se um navegador não for compatível com um elemento HTML, ele não será mostrado. Isso significa que, se você tiver o elemento <permission> no código HTML, nada vai acontecer se o navegador não o conhecer. Ainda é possível detectar o suporte usando JavaScript, por exemplo, para criar uma solicitação de permissão acionada por um clique de um <button> normal.

if ('HTMLPermissionElement' in window) {
  // The `<permission>` element is supported.
}

Teste de origem

Para testar o elemento <permission> no seu site com usuários reais, inscreva-se no teste de origem. Leia Começar a usar os testes de origem para instruções sobre como preparar seu site para usar os testes de origem. O teste de origem será executado do Chrome 126 ao 131 (19 de fevereiro de 2025).

Demonstração

Confira a demonstração e confira o código-fonte no GitHub. Esta é uma captura de tela da experiência em um navegador compatível.

Demonstração do elemento de permissão mostrando três botões.

Feedback

Queremos saber como o <permission> funciona para seu caso de uso. Fique à vontade para responder a um dos Problemas no repositório ou registre um novo. Os indicadores públicos no repo do elemento <permission> vão permitir que nós e outros navegadores saibamos que você tem interesse nele.

Perguntas frequentes

  • Por que isso é melhor do que um <button> normal associado à API Permissions? Um clique em um <button> é um gesto do usuário, mas os navegadores não têm como verificar se ele está conectado à solicitação de permissão. Se o usuário clicou em um <permission>, o navegador pode ter certeza de que o clique está relacionado a uma solicitação de permissão. Isso permite que o navegador facilite fluxos que, de outra forma, seriam muito mais arriscados. Por exemplo, permitindo que o usuário desfaça facilmente o bloqueio de uma permissão.
  • E se outros navegadores não forem compatíveis com o elemento <permission>? O elemento <permission> pode ser usado como um aprimoramento progressivo. Em navegadores sem suporte, é possível usar um fluxo de permissão clássico. Por exemplo, com base no clique de um <button> normal. A equipe de permissões também está trabalhando em um polyfill. Marque o repositório do GitHub com estrela para receber uma notificação quando ele estiver pronto.
  • Isso foi discutido com outros fornecedores de navegadores? O elemento <permission> foi discutido ativamente no W3C TPAC em 2023 em uma sessão de discussão. Leia as notas da sessão pública. A equipe do Chrome também pediu posições formais de padrões dos dois fornecedores. Consulte a seção Links relacionados. O elemento <permission> é um tema de discussão em andamento com outros navegadores, e esperamos padronizá-lo.
  • Esse elemento precisa ser vazio? Ainda está sendo ativamente debatido se <permission> precisa ser um elemento vazio ou não. Se você tiver feedback, participe do problema.

Agradecimentos

Este documento foi revisado por Balázs Engedy, Thomas Nguyen, Penelope McLachlan, Marian Harbach, David Warren e Rachel Andrew.