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.
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.
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.
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.
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 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.
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.
Se eles permitiram o recurso antes, podem continuar permitindo ou desativá-lo.
Se eles já haviam proibido um recurso, podem continuar não permitindo ou permitir dessa 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.
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 |
---|---|
|
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 . |
|
Os valores negativos serão corrigidos para 0 . |
margin (tudo) |
Os valores negativos serão corrigidos para 0 . |
|
Os 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 . Os valores abaixo de 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 abaixo de -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,
o valor máximo calculado entre o padrão e os valores
fornecidos será considerado. |
|
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. |
|
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 . |
|
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. . |
|
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 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 indicada 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 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.
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.
Links relacionados
Agradecimentos
Este documento foi revisado por Balázs Engedy, Thomas Nguyen, Penelope McLachlan, Marian Harbach, David Warren e Rachel Andrew.