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.
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.
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.
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.
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.
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.
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.
Se o usuário já havia permitido o recurso antes, pode continuar permitindo ou não.
Se um recurso foi bloqueado antes, é possível continuar com essa restrição 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 seguinte para conferir os dois estados.
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 |
---|---|
|
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. |
|
Precisa ser definido no equivalente de small e
xxxlarge . Caso contrário, o elemento será desativado. O zoom será considerado ao calcular font-size . |
|
Valores negativos serão corrigidos para 0 . |
margin (tudo) |
Valores negativos serão corrigidos para 0 . |
|
Valores abaixo de 200 serão corrigidos para 200 . |
|
Valores diferentes de normal e italic serão corrigidos para normal . |
|
Valores acima de 0.5em serão corrigidos para 0.5em . Valores em 0 serão corrigidos para 0 . |
|
Valores diferentes de inline-block e none
serão corrigidos para inline-block . |
|
Valores acima de 0.2em serão corrigidos para 0.2em . Os valores em -0.05em serão corrigidos para -0.05em . |
|
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. |
|
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. |
|
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. |
|
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. |
|
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 . |
|
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. |
|
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 asborder-*
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 paraoutline-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.
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.
Links relacionados
Agradecimentos
Este documento foi revisado por Balázs Engedy, Thomas Nguyen, Penelope McLachlan, Marian Harbach, David Warren e Rachel Andrew.