Introdução à API Budget

A API Push Messaging permite enviar notificações para um usuário mesmo quando o navegador está fechado. Muitos desenvolvedores querem usar essas mensagens para atualizar e sincronizar conteúdo sem que o navegador esteja aberto, mas a API tem uma restrição importante: é preciso sempre mostrar uma notificação para cada mensagem push recebida.

Poder enviar uma mensagem push para sincronizar dados no dispositivo de um usuário ou ocultar uma notificação mostrada anteriormente pode ser extremamente útil para usuários e desenvolvedores, mas permitir que um app da Web funcione em segundo plano sem que o usuário saiba está sujeito a abusos.

A API Budget é uma nova API projetada para permitir que os desenvolvedores realizem um trabalho em segundo plano limitado sem notificar o usuário, como push silencioso ou uma busca em segundo plano. No Chrome 60 e versões mais recentes, você poderá começar a usar essa API, e a equipe do Chrome está ansiosa para receber feedback dos desenvolvedores.

Para permitir que os desenvolvedores consumam os recursos de um usuário em segundo plano, a plataforma da Web está introduzindo o conceito de um orçamento usando a nova API Budget. Cada site vai receber uma quantidade de recursos com base no engajamento do usuário que eles podem consumir para ações em segundo plano, como um push silencioso, em que cada operação vai esgotar o orçamento. Quando o orçamento é gasto, as ações em segundo plano não podem mais ser executadas sem a visibilidade do usuário. O user agent será responsável por determinar o orçamento atribuído a um app da Web com base na heurística dele. Por exemplo, uma permissão de orçamento pode ser vinculada ao engajamento do usuário. Cada navegador pode decidir a própria heurística.

Texto longo, leia o resumo: a API Budget permite reservar e usar o orçamento, receber uma lista do orçamento restante e entender o custo das operações em segundo plano.

Orçamento de reserva

No Chrome 60 e versões mais recentes, o método navigator.budget.reserve() estará disponível sem flags.

O método reserve() permite solicitar orçamento para uma operação específica e retorna um booleano para indicar se o orçamento pode ser reservado. Se o orçamento foi reservado, não é necessário notificar o usuário sobre seu trabalho em segundo plano.

No exemplo de notificações push, é possível tentar reservar orçamento para uma operação de envio silencioso e, se reserve() for resolvido com verdadeiro, a operação será permitida. Caso contrário, ele vai retornar falso e você vai precisar mostrar uma notificação.

self.addEventListener('push', event => {
 const promiseChain = navigator.budget.reserve('silent-push')
   .then((reserved) => {
     if (reserved) {
       // No need to show a notification.
       return;
     }

     // Not enough budget is available, must show a notification.
     return registration.showNotification(...);
   });
 event.waitUntil(promiseChain);
});

No Chrome 60, "push silencioso" é o único tipo de operação disponível, mas você pode encontrar uma lista completa de tipos de operação na especificação. Também não há uma maneira fácil de aumentar o orçamento para fins de teste ou depuração depois que ele for usado, mas, como solução temporária, você pode criar um novo perfil no Chrome. Infelizmente, não é possível usar o modo de navegação anônima para isso, porque a API Budget retorna um orçamento de zero no modo de navegação anônima (embora haja um bug que resulta em um erro durante meus testes).

Chame reserve() apenas quando você pretende realizar a operação que está reservando em algum momento no futuro. Se você chamou a reserva no exemplo acima, mas ainda mostrou uma notificação, o orçamento ainda será usado.

Um caso de uso comum que não é ativado por reserve() sozinho é a capacidade de programar um push silencioso de um back-end. Ela tem APIs para permitir esse caso de uso, mas elas ainda estão em desenvolvimento no Chrome e, no momento, estão disponíveis apenas com flags e / ou um teste de origem.

Testes de origem e API Budget

Há dois métodos, getBudget() e getCost(), que podem ser usados por um app da Web para planejar o uso do orçamento.

No Chrome 60, esses dois métodos estão disponíveis se você se inscrever no teste de origem. Para testes, você pode usá-los localmente ativando a flag "Experimental Web Platform features" (abra chrome://flags/#enable-experimental-web-platform-features no Chrome).

Vamos conferir como usar essas APIs.

Acessar seu orçamento

É possível encontrar o orçamento disponível com o método getBudget(). Alguns navegadores (como o Chrome) vão ter um "decaimento" de orçamento ao longo do tempo. Para oferecer visibilidade total, isso retorna uma matriz de BudgetStates, indicando qual será seu orçamento em vários momentos no futuro.

Para listar as entradas de orçamento que podemos executar:

navigator.budget.getBudget()
.then((budgets) => {
  budgets.forEach((element) => {
    console.log(\`At '${new Date(element.time).toString()}' \` +
      \`your budget will be '${element.budgetAt}'.\`);
  });
});

A primeira entrada será seu orçamento atual, e os valores adicionais vão mostrar qual será seu orçamento em vários pontos no futuro.

At 'Mon Jun 05 2017 12:47:20' you will have a budget of '3'.
At 'Fri Jun 09 2017 10:42:57' you will have a budget of '2'.
At 'Fri Jun 09 2017 12:31:09' you will have a budget of '1'.

Um dos benefícios de incluir os limites de orçamento futuros é que os desenvolvedores podem compartilhar essas informações com o back-end para adaptar o comportamento do lado do servidor, ou seja, enviar uma mensagem push apenas para acionar uma atualização quando o cliente tiver orçamento para um push silencioso.

Conferir o custo de uma operação

Para descobrir o custo de uma operação, a chamada getCost() vai retornar um número indicando o valor máximo de orçamento que será consumido se você chamar reserve() para essa operação.

Por exemplo, podemos descobrir o custo de não mostrar uma notificação quando você recebe uma mensagem push (ou seja, o custo de um push silencioso) com o seguinte código:

navigator.budget.getCost('silent-push')
.then((cost) => {
  console.log('Cost of silent push is:', cost);
})
.catch((err) => {
  console.error('Unable to get cost:', err);
});

No momento em que este artigo for escrito, o Chrome 60 imprimirá:

Cost of silent push is: 2

Algo a ser destacado com os métodos reserve() e getCost() é que o custo real de uma operação pode ser menor que o custo retornado por getCost(). Você ainda poderá reservar uma operação se o orçamento atual for menor do que o custo indicado. Veja os detalhes específicos da especificação a seguir:

Essa é a API atual no Chrome, e como a Web continua oferecendo suporte a novas APIs que exigem a capacidade de executar trabalhos em segundo plano, como a busca em segundo plano, a API Budget pode ser usada para gerenciar o número de operações que você pode realizar sem notificar o usuário.

Ao usar a API, envie feedback no repositório do GitHub ou relate bugs do Chrome em crbug.com.