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

Há uma série de métodos imperativos para pedir permissão para usar recursos avançados, como o acesso à localização em apps da Web. Esses métodos apresentam vários desafios. Por isso, a equipe de permissões do Chrome está testando um novo método declarativo: um elemento HTML <permission> dedicado. Esse elemento está em teste de origem do 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 requer o local do usuário usando a API Geolocation, os navegadores solicitam o local, 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 ou solicitar explicitamente com antecedência

A API Geolocation é uma API poderosa e depende da abordagem de solicitação no primeiro uso. Por exemplo, quando um app chama o método navigator.geolocation.getCurrentPosition(), a solicitação de permissões 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 pedir 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 apareceria antes de o usuário interagir 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 de acesso ao microfone exibida ao carregar um site.

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

O spam de permissão fez com que os fornecedores de navegadores exigiam um gesto do usuário, como um clique de botão ou um evento de keydown, antes de mostrar uma solicitação de permissão. O problema com essa abordagem é que é muito difícil, se não impossível, para o navegador descobrir se um determinado gesto do usuário precisa resultar em uma solicitação de permissão a ser mostrada ou não. Talvez o usuário estivesse apenas clicando na página, frustrado em qualquer lugar porque a página demorou para carregar, ou talvez estivesse realmente clicando no botão Localizar-me. 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 comandos, como bloquear completamente recursos no início ou mostrar a solicitação de permissão de uma maneira não modal e menos intrusiva.

Navegador Chrome mostrando um

Contextualização de permissões

Outro desafio, especialmente em telas grandes, é a forma como a solicitação de permissão é mostrada com frequência: acima da linha de morte, ou seja, fora da área da janela do navegador em que o app pode desenhar. É muito comum que os usuários percam a solicitação na parte superior da janela do navegador ao clicar em um botão na parte inferior da janela. Esse problema geralmente é agravado quando há mitigações de spam do navegador.

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

Não é fácil desfazer

Finalmente, é muito fácil para os usuários navegarem por si mesmos em um beco sem saída. Por exemplo, quando o usuário bloqueia o acesso a um recurso, é necessário que ele esteja ciente da lista suspensa de informações do site, em que é possível Redefinir permissões ou ativar novamente 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 oferecem um atalho fácil para os usuários mudarem um estado de permissão e precisam explicar detalhadamente como mudar as configurações, conforme mostrado na parte de baixo da captura de tela do Google Maps a seguir.

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 no Chrome.

Um elemento <permission> declarativo

Para enfrentar 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 debatedo ativamente se <permission> deve ser um elemento vazio ou não. Um elemento vazio é um elemento que se fecha automaticamente em HTML que não pode ter nenhum nó filho. Isso significa, em HTML, que ele pode não ter uma tag final.

O atributo type

O atributo type contém uma lista separada por espaços das permissões solicitadas. No momento da redação deste artigo, os valores permitidos são '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.

Diversos botões de elementos de permissão com permissão de câmera, microfone e câmera, além do microfone.

O atributo type-ext

Para algumas permissões que permitem outros parâmetros, 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 precisa ser consistente, portanto, 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> por conta própria. Se o elemento <permission> continuar além 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ê tiver interesse em usar o elemento <permission> e precisar de uma string ou ícone específico, entre em contato.

Comportamento

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

  • Se eles não tinham permitido um recurso antes, podem permitir o recurso em todas as visitas ou no acesso atual.

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

  • Se o usuário já havia permitido o recurso antes, pode continuar permitindo ou não.

    Solicitação de permissão para continuar permitindo ou não dar permissão.

  • Se um recurso foi bloqueado antes, é possível continuar com essa restrição ou permitir desta vez.

    Permissão para continuar não permitindo ou não dar esse período.

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 seguinte para conferir os dois estados.

Botões de permissão com os textos

Design de CSS

Para garantir que os usuários possam reconhecer facilmente o botão como uma plataforma para acessar recursos avançados, o estilo do elemento <permission> é restrito. Se as restrições de estilo não funcionarem para seu caso de uso, adoraríamos saber como e por quê. 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 incluirá 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

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

font-weight

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. Valores em 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 em -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, será considerado o valor máximo calculado entre o padrão e os valores fornecidos.

max-width

Vai ter um valor padrão de três vezes fit-content. Se fornecido, 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 como 1em e padding-bottom serão definidos 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 como 5em e padding-right serão definidos como o valor de padding-left.

transform

Efeitos visuais distorcidos não serão permitidos. Por enquanto, aceitamos apenas translação 2D e escalonamento vertical proporcional.

As seguintes propriedades CSS 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 observada 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 das equivalentes.

Pseudoclasses

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

  • :granted: a pseudoclasse :granted permite um estilo especial quando uma permissão é concedida.
  • :invalid: a pseudoclasse :invalid permite um estilo especial quando o elemento está em um estado inválido, por exemplo, quando é 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> precisa ser usado com a API Permissions. É possível detectar vários eventos:

  • onpromptdismiss: este evento é disparado quando a solicitação de permissão acionada pelo elemento é dispensada pelo usuário, por exemplo, clicando no botão "Fechar" ou clicando fora da solicitação.

  • onpromptaction: esse evento é disparado quando a solicitação de permissão acionada pelo elemento é resolvida pelo usuário que realiza alguma ação na solicitação. 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: este evento é disparado 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 in-line no código HTML (<permission type="…" onpromptdismiss="alert('The prompt was dismissed');" />) ou usando addEventListener() no elemento <permission>, conforme mostrado no exemplo a seguir.

<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 tiver suporte para um elemento HTML, ele não o exibirá. Isso significa que, se você tiver o elemento <permission> no código HTML, nada acontecerá se o navegador não o souber. 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 o artigo Começar a usar testes de origem para conferir instruções sobre como preparar seu site para esses testes. O teste de origem será executado no 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 no seu caso de uso. Fique à vontade para responder a um dos Problemas no repositório ou registre um novo. Os indicadores públicos no repositório para o elemento <permission> informarão ao Google e a outros navegadores que você tem interesse nele.

Perguntas frequentes

  • Como isso é melhor do que um <button> normal pareado com a API Permissions? O clique de um <button> é um gesto do usuário, mas os navegadores não têm como verificar se ele está conectado à solicitação para pedir 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, permitir 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 temática. Leia as notas da sessão pública. A equipe do Chrome também solicitou posições de padrão formais de ambos os fornecedores. Consulte a seção Links relacionados. O elemento <permission> é um tema contínuo de discussões com outros navegadores e esperamos padronizá-lo.
  • Esse elemento deveria mesmo ser um vazio? Ainda estamos debatendo ativamente se <permission> deve ser um elemento vazio ou não. Se você tiver feedback, entre no assunto.

Agradecimentos

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